Index: /trunk/src/VBox/RDP/client-1.8.3/COPYING
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/COPYING	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/COPYING	(revision 55121)
@@ -0,0 +1,676 @@
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+ 
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+  
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
Index: /trunk/src/VBox/RDP/client-1.8.3/Makefile.in
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/Makefile.in	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/Makefile.in	(revision 55121)
@@ -0,0 +1,165 @@
+#
+# rdesktop: A Remote Desktop Protocol client
+# Makefile.in
+# Copyright (C) Matthew Chapman 1999-2007
+#
+
+prefix      = @prefix@
+exec_prefix = @exec_prefix@
+bindir      = @bindir@
+mandir      = @mandir@
+datarootdir = @datarootdir@
+datadir     = @datadir@
+
+VERSION     = @PACKAGE_VERSION@
+KEYMAP_PATH = $(datadir)/rdesktop/keymaps/
+
+CC          = @CC@
+INSTALL     = @INSTALL@
+CFLAGS      = @CFLAGS@ @X_CFLAGS@ @DEFS@ -DKEYMAP_PATH=\"$(KEYMAP_PATH)\"
+LDFLAGS     = @LDFLAGS@ @LIBS@ @X_LIBS@ @X_EXTRA_LIBS@
+STRIP       = @STRIP@
+
+TARGETS     = rdesktop @RDP2VNCTARGET@
+VNCINC      = @VNCINC@
+LDVNC       = @LDVNC@
+VNCLINK     = @VNCLINK@
+SOUNDOBJ    = @SOUNDOBJ@
+SCARDOBJ    = @SCARDOBJ@
+CREDSSPOBJ  = @CREDSSPOBJ@
+
+RDPOBJ   = tcp.o asn.o iso.o mcs.o secure.o licence.o rdp.o orders.o bitmap.o cache.o rdp5.o channels.o rdpdr.o serial.o printer.o disk.o parallel.o printercache.o mppc.o pstcache.o lspci.o seamless.o ssl.o utils.o
+X11OBJ   = rdesktop.o xwin.o xkeymap.o ewmhints.o xclip.o cliprdr.o ctrl.o
+VNCOBJ   = vnc/rdp2vnc.o vnc/vnc.o vnc/xkeymap.o vnc/x11stubs.o
+
+.PHONY: all
+all: $(TARGETS)
+
+rdesktop: $(X11OBJ) $(SOUNDOBJ) $(RDPOBJ) $(SCARDOBJ) $(CREDSSPOBJ)
+	$(CC) $(CFLAGS) -o rdesktop $(X11OBJ) $(SOUNDOBJ) $(RDPOBJ) $(SCARDOBJ) $(CREDSSPOBJ) $(LDFLAGS) -lX11
+
+rdp2vnc: $(VNCOBJ) $(SOUNDOBJ) $(RDPOBJ) $(SCARDOBJ) $(CREDSSPOBJ)
+	$(VNCLINK) $(CFLAGS) -o rdp2vnc $(VNCOBJ) $(SOUNDOBJ) $(RDPOBJ) $(SCARDOBJ) $(CREDSSPOBJ) $(LDFLAGS) $(LDVNC)
+
+vnc/rdp2vnc.o: rdesktop.c
+	$(CC) $(CFLAGS) $(VNCINC) -DRDP2VNC -o vnc/rdp2vnc.o -c rdesktop.c
+
+vnc/vnc.o: vnc/vnc.c
+	$(CC) $(CFLAGS) $(VNCINC) -DRDP2VNC -o vnc/vnc.o -c vnc/vnc.c
+
+vnc/xkeymap.o: xkeymap.c
+	$(CC) $(CFLAGS) $(VNCINC) -DRDP2VNC -o vnc/xkeymap.o -c xkeymap.c
+
+vnc/x11stubs.o: vnc/x11stubs.c
+	$(CC) $(CFLAGS) $(VNCINC) -o vnc/x11stubs.o -c vnc/x11stubs.c
+
+.PHONY: install
+install: installbin installkeymaps installman
+
+.PHONY: installbin
+installbin: rdesktop
+	mkdir -p $(DESTDIR)$(bindir)
+	$(INSTALL) rdesktop $(DESTDIR)$(bindir)
+	$(STRIP) $(DESTDIR)$(bindir)/rdesktop
+	chmod 755 $(DESTDIR)$(bindir)/rdesktop
+
+.PHONY: installman
+installman: doc/rdesktop.1
+	mkdir -p $(DESTDIR)$(mandir)/man1
+	cp doc/rdesktop.1 $(DESTDIR)$(mandir)/man1
+	chmod 644 $(DESTDIR)$(mandir)/man1/rdesktop.1
+
+.PHONY: installkeymaps
+installkeymaps:
+	mkdir -p $(DESTDIR)$(KEYMAP_PATH)
+# Prevent copying the CVS directory
+	cp keymaps/?? keymaps/??-?? $(DESTDIR)$(KEYMAP_PATH)
+	cp keymaps/common $(DESTDIR)$(KEYMAP_PATH)
+	cp keymaps/modifiers $(DESTDIR)$(KEYMAP_PATH)
+	chmod 644 $(DESTDIR)$(KEYMAP_PATH)/*
+
+.PHONY: proto
+proto:
+	cat proto.head > proto.h
+	cproto -DMAKE_PROTO \
+	bitmap.c cache.c channels.c cliprdr.c disk.c mppc.c ewmhints.c	\
+	iso.c licence.c mcs.c orders.c parallel.c printer.c printercache.c \
+	pstcache.c rdesktop.c rdp5.c rdp.c rdpdr.c rdpsnd.c \
+	secure.c serial.c tcp.c xclip.c xkeymap.c xwin.c lspci.c seamless.c \
+	scard.c >> proto.h
+	cat proto.tail >> proto.h
+
+.PHONY: clean
+clean:
+	rm -f *.o *~ vnc/*.o vnc/*~ rdesktop rdp2vnc
+
+.PHONY: distclean
+distclean: clean
+	rm -rf autom4te.cache config.log config.status Makefile rdesktop-$(VERSION).tar.gz
+
+.PHONY: dist
+dist: rdesktop-$(VERSION).tar.gz
+
+rdesktop-$(VERSION).tar.gz: Makefile configure
+	mkdir -p /tmp/rdesktop-make-dist-dir
+	ln -sf `pwd` /tmp/rdesktop-make-dist-dir/rdesktop-$(VERSION)
+	(cd /tmp/rdesktop-make-dist-dir; \
+	tar zcvf rdesktop-$(VERSION)/rdesktop-$(VERSION).tar.gz \
+	rdesktop-$(VERSION)/COPYING \
+	rdesktop-$(VERSION)/README \
+	rdesktop-$(VERSION)/configure \
+	rdesktop-$(VERSION)/configure.ac \
+	rdesktop-$(VERSION)/config.sub \
+	rdesktop-$(VERSION)/config.guess \
+	rdesktop-$(VERSION)/bootstrap \
+	rdesktop-$(VERSION)/install-sh \
+	rdesktop-$(VERSION)/Makefile.in \
+	rdesktop-$(VERSION)/rdesktop.spec \
+	rdesktop-$(VERSION)/*.c \
+	rdesktop-$(VERSION)/*.h \
+	rdesktop-$(VERSION)/proto.head \
+	rdesktop-$(VERSION)/proto.tail \
+	rdesktop-$(VERSION)/keymaps/?? \
+	rdesktop-$(VERSION)/keymaps/??-?? \
+	rdesktop-$(VERSION)/keymaps/common \
+	rdesktop-$(VERSION)/keymaps/modifiers \
+	rdesktop-$(VERSION)/keymaps/convert-map \
+	rdesktop-$(VERSION)/doc/HACKING \
+	rdesktop-$(VERSION)/doc/AUTHORS \
+	rdesktop-$(VERSION)/doc/TODO \
+	rdesktop-$(VERSION)/doc/ChangeLog \
+	rdesktop-$(VERSION)/doc/keymapping.txt \
+	rdesktop-$(VERSION)/doc/keymap-names.txt \
+	rdesktop-$(VERSION)/doc/ipv6.txt \
+	rdesktop-$(VERSION)/doc/licensing.txt \
+	rdesktop-$(VERSION)/doc/patches.txt \
+	rdesktop-$(VERSION)/doc/redirection.txt \
+	rdesktop-$(VERSION)/doc/rdesktop.1 )
+	rm -rf /tmp/rdesktop-make-dist-dir
+
+.PHONY: dist-noversion
+dist-noversion: rdesktop.tar.gz
+
+rdesktop.tar.gz: rdesktop-$(VERSION).tar.gz
+	mkdir -p /tmp/rdesktop-make-dist-dir
+	tar zxvf $< -C /tmp/rdesktop-make-dist-dir
+	mv /tmp/rdesktop-make-dist-dir/rdesktop-$(VERSION) /tmp/rdesktop-make-dist-dir/rdesktop
+	ls /tmp/rdesktop-make-dist-dir/rdesktop
+	tar zcvf $@ -C /tmp/rdesktop-make-dist-dir rdesktop
+	rm -rf /tmp/rdesktop-make-dist-dir
+
+Makefile: Makefile.in configure
+	./config.status
+
+configure: configure.ac
+	./bootstrap
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+
+.c.o:
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+.PHONY: doc/AUTHORS
+doc/AUTHORS:
+	./genauthors *.c
Index: /trunk/src/VBox/RDP/client-1.8.3/README
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/README	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/README	(revision 55121)
@@ -0,0 +1,50 @@
+==========================================
+rdesktop: A Remote Desktop Protocol client
+==========================================
+
+rdesktop is an open source client for Microsoft's RDP protocol. It is
+known to work with Windows versions such as NT 4 Terminal Server,
+2000, XP, 2003, 2003 R2, Vista, 2008, 7, and 2008 R2. rdesktop
+currently implements the RDP version 4 and 5 protocols.
+
+Installation
+------------
+rdesktop uses a GNU-style build procedure.  Typically all that is necessary
+to install rdesktop is the following::
+
+	% ./configure
+	% make
+	% make install
+
+The default is to install under /usr/local.  This can be changed by adding
+--prefix=directory to the configure line.
+
+Note for Subversion users
+-------------------------
+If you have downloaded a snapshot of rdesktop using Subversion, you
+will first need to run ./bootstrap in order to generate the build
+infrastructure.  This is not necessary for release versions of
+rdesktop.
+
+Invocation
+----------
+Simply run::
+
+	% rdesktop server
+
+where server is the name of the Terminal Services machine.  (If you receive
+"Connection refused", this probably means that the server does not have
+Terminal Services enabled, or there is a firewall blocking access.)
+
+You can also specify a number of options on the command line.  These are listed
+in the rdesktop manual page (run "man rdesktop").
+
+Smart-card support notes
+------------------------
+The smart-card support module uses PCSC-lite. You should use PCSC-lite 1.2.9 or
+later.
+
+To enable smart-card support in the rdesktop just run "./configure" with the
+"--enable-smartcard" option. Also you can enable smart-card debug with
+additional "--with-debug-smartcard" option.
+
Index: /trunk/src/VBox/RDP/client-1.8.3/asn.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/asn.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/asn.c	(revision 55121)
@@ -0,0 +1,109 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   ASN.1 utility functions
+   Copyright 2012 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+
+
+/* Parse an ASN.1 BER header */
+RD_BOOL
+ber_parse_header(STREAM s, int tagval, int *length)
+{
+	int tag, len;
+
+	if (tagval > 0xff)
+	{
+		in_uint16_be(s, tag);
+	}
+	else
+	{
+		in_uint8(s, tag);
+	}
+
+	if (tag != tagval)
+	{
+		error("expected tag %d, got %d\n", tagval, tag);
+		return False;
+	}
+
+	in_uint8(s, len);
+
+	if (len & 0x80)
+	{
+		len &= ~0x80;
+		*length = 0;
+		while (len--)
+			next_be(s, *length);
+	}
+	else
+		*length = len;
+
+	return s_check(s);
+}
+
+/* Output an ASN.1 BER header */
+void
+ber_out_header(STREAM s, int tagval, int length)
+{
+	if (tagval > 0xff)
+	{
+		out_uint16_be(s, tagval);
+	}
+	else
+	{
+		out_uint8(s, tagval);
+	}
+
+	if (length >= 0x80)
+	{
+		out_uint8(s, 0x82);
+		out_uint16_be(s, length);
+	}
+	else
+		out_uint8(s, length);
+}
+
+/* Output an ASN.1 BER integer */
+void
+ber_out_integer(STREAM s, int value)
+{
+	ber_out_header(s, BER_TAG_INTEGER, 2);
+	out_uint16_be(s, value);
+}
+
+RD_BOOL
+ber_in_header(STREAM s, int *tagval, int *decoded_len)
+{
+	in_uint8(s, *tagval);
+	in_uint8(s, *decoded_len);
+
+	if (*decoded_len < 0x80)
+		return True;
+	else if (*decoded_len == 0x81)
+	{
+		in_uint8(s, *decoded_len);
+		return True;
+	}
+	else if (*decoded_len == 0x82)
+	{
+		in_uint16_be(s, *decoded_len);
+		return True;
+	}
+
+	return False;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/bitmap.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/bitmap.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/bitmap.c	(revision 55121)
@@ -0,0 +1,909 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Bitmap decompression routines
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* three seperate function for speed when decompressing the bitmaps
+   when modifing one function make the change in the others
+   jay.sorg@gmail.com */
+
+/* indent is confused by this file */
+/* *INDENT-OFF* */
+
+#include "rdesktop.h"
+
+#define CVAL(p)   (*(p++))
+#ifdef NEED_ALIGN
+#ifdef L_ENDIAN
+#define CVAL2(p, v) { v = (*(p++)); v |= (*(p++)) << 8; }
+#else
+#define CVAL2(p, v) { v = (*(p++)) << 8; v |= (*(p++)); }
+#endif /* L_ENDIAN */
+#else
+#define CVAL2(p, v) { v = (*((uint16*)p)); p += 2; }
+#endif /* NEED_ALIGN */
+
+#define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
+
+#define REPEAT(statement) \
+{ \
+	while((count & ~0x7) && ((x+8) < width)) \
+		UNROLL8( statement; count--; x++; ); \
+	\
+	while((count > 0) && (x < width)) \
+	{ \
+		statement; \
+		count--; \
+		x++; \
+	} \
+}
+
+#define MASK_UPDATE() \
+{ \
+	mixmask <<= 1; \
+	if (mixmask == 0) \
+	{ \
+		mask = fom_mask ? fom_mask : CVAL(input); \
+		mixmask = 1; \
+	} \
+}
+
+/* 1 byte bitmap decompress */
+static RD_BOOL
+bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
+{
+	uint8 *end = input + size;
+	uint8 *prevline = NULL, *line = NULL;
+	int opcode, count, offset, isfillormix, x = width;
+	int lastopcode = -1, insertmix = False, bicolour = False;
+	uint8 code;
+	uint8 colour1 = 0, colour2 = 0;
+	uint8 mixmask, mask = 0;
+	uint8 mix = 0xff;
+	int fom_mask = 0;
+
+	while (input < end)
+	{
+		fom_mask = 0;
+		code = CVAL(input);
+		opcode = code >> 4;
+		/* Handle different opcode forms */
+		switch (opcode)
+		{
+			case 0xc:
+			case 0xd:
+			case 0xe:
+				opcode -= 6;
+				count = code & 0xf;
+				offset = 16;
+				break;
+			case 0xf:
+				opcode = code & 0xf;
+				if (opcode < 9)
+				{
+					count = CVAL(input);
+					count |= CVAL(input) << 8;
+				}
+				else
+				{
+					count = (opcode < 0xb) ? 8 : 1;
+				}
+				offset = 0;
+				break;
+			default:
+				opcode >>= 1;
+				count = code & 0x1f;
+				offset = 32;
+				break;
+		}
+		/* Handle strange cases for counts */
+		if (offset != 0)
+		{
+			isfillormix = ((opcode == 2) || (opcode == 7));
+			if (count == 0)
+			{
+				if (isfillormix)
+					count = CVAL(input) + 1;
+				else
+					count = CVAL(input) + offset;
+			}
+			else if (isfillormix)
+			{
+				count <<= 3;
+			}
+		}
+		/* Read preliminary data */
+		switch (opcode)
+		{
+			case 0:	/* Fill */
+				if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
+					insertmix = True;
+				break;
+			case 8:	/* Bicolour */
+				colour1 = CVAL(input);
+			case 3:	/* Colour */
+				colour2 = CVAL(input);
+				break;
+			case 6:	/* SetMix/Mix */
+			case 7:	/* SetMix/FillOrMix */
+				mix = CVAL(input);
+				opcode -= 5;
+				break;
+			case 9:	/* FillOrMix_1 */
+				mask = 0x03;
+				opcode = 0x02;
+				fom_mask = 3;
+				break;
+			case 0x0a:	/* FillOrMix_2 */
+				mask = 0x05;
+				opcode = 0x02;
+				fom_mask = 5;
+				break;
+		}
+		lastopcode = opcode;
+		mixmask = 0;
+		/* Output body */
+		while (count > 0)
+		{
+			if (x >= width)
+			{
+				if (height <= 0)
+					return False;
+				x = 0;
+				height--;
+				prevline = line;
+				line = output + height * width;
+			}
+			switch (opcode)
+			{
+				case 0:	/* Fill */
+					if (insertmix)
+					{
+						if (prevline == NULL)
+							line[x] = mix;
+						else
+							line[x] = prevline[x] ^ mix;
+						insertmix = False;
+						count--;
+						x++;
+					}
+					if (prevline == NULL)
+					{
+						REPEAT(line[x] = 0)
+					}
+					else
+					{
+						REPEAT(line[x] = prevline[x])
+					}
+					break;
+				case 1:	/* Mix */
+					if (prevline == NULL)
+					{
+						REPEAT(line[x] = mix)
+					}
+					else
+					{
+						REPEAT(line[x] = prevline[x] ^ mix)
+					}
+					break;
+				case 2:	/* Fill or Mix */
+					if (prevline == NULL)
+					{
+						REPEAT
+						(
+							MASK_UPDATE();
+							if (mask & mixmask)
+								line[x] = mix;
+							else
+								line[x] = 0;
+						)
+					}
+					else
+					{
+						REPEAT
+						(
+							MASK_UPDATE();
+							if (mask & mixmask)
+								line[x] = prevline[x] ^ mix;
+							else
+								line[x] = prevline[x];
+						)
+					}
+					break;
+				case 3:	/* Colour */
+					REPEAT(line[x] = colour2)
+					break;
+				case 4:	/* Copy */
+					REPEAT(line[x] = CVAL(input))
+					break;
+				case 8:	/* Bicolour */
+					REPEAT
+					(
+						if (bicolour)
+						{
+							line[x] = colour2;
+							bicolour = False;
+						}
+						else
+						{
+							line[x] = colour1;
+							bicolour = True; count++;
+						}
+					)
+					break;
+				case 0xd:	/* White */
+					REPEAT(line[x] = 0xff)
+					break;
+				case 0xe:	/* Black */
+					REPEAT(line[x] = 0)
+					break;
+				default:
+					unimpl("bitmap opcode 0x%x\n", opcode);
+					return False;
+			}
+		}
+	}
+	return True;
+}
+
+/* 2 byte bitmap decompress */
+static RD_BOOL
+bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
+{
+	uint8 *end = input + size;
+	uint16 *prevline = NULL, *line = NULL;
+	int opcode, count, offset, isfillormix, x = width;
+	int lastopcode = -1, insertmix = False, bicolour = False;
+	uint8 code;
+	uint16 colour1 = 0, colour2 = 0;
+	uint8 mixmask, mask = 0;
+	uint16 mix = 0xffff;
+	int fom_mask = 0;
+
+	while (input < end)
+	{
+		fom_mask = 0;
+		code = CVAL(input);
+		opcode = code >> 4;
+		/* Handle different opcode forms */
+		switch (opcode)
+		{
+			case 0xc:
+			case 0xd:
+			case 0xe:
+				opcode -= 6;
+				count = code & 0xf;
+				offset = 16;
+				break;
+			case 0xf:
+				opcode = code & 0xf;
+				if (opcode < 9)
+				{
+					count = CVAL(input);
+					count |= CVAL(input) << 8;
+				}
+				else
+				{
+					count = (opcode < 0xb) ? 8 : 1;
+				}
+				offset = 0;
+				break;
+			default:
+				opcode >>= 1;
+				count = code & 0x1f;
+				offset = 32;
+				break;
+		}
+		/* Handle strange cases for counts */
+		if (offset != 0)
+		{
+			isfillormix = ((opcode == 2) || (opcode == 7));
+			if (count == 0)
+			{
+				if (isfillormix)
+					count = CVAL(input) + 1;
+				else
+					count = CVAL(input) + offset;
+			}
+			else if (isfillormix)
+			{
+				count <<= 3;
+			}
+		}
+		/* Read preliminary data */
+		switch (opcode)
+		{
+			case 0:	/* Fill */
+				if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
+					insertmix = True;
+				break;
+			case 8:	/* Bicolour */
+				CVAL2(input, colour1);
+			case 3:	/* Colour */
+				CVAL2(input, colour2);
+				break;
+			case 6:	/* SetMix/Mix */
+			case 7:	/* SetMix/FillOrMix */
+				CVAL2(input, mix);
+				opcode -= 5;
+				break;
+			case 9:	/* FillOrMix_1 */
+				mask = 0x03;
+				opcode = 0x02;
+				fom_mask = 3;
+				break;
+			case 0x0a:	/* FillOrMix_2 */
+				mask = 0x05;
+				opcode = 0x02;
+				fom_mask = 5;
+				break;
+		}
+		lastopcode = opcode;
+		mixmask = 0;
+		/* Output body */
+		while (count > 0)
+		{
+			if (x >= width)
+			{
+				if (height <= 0)
+					return False;
+				x = 0;
+				height--;
+				prevline = line;
+				line = ((uint16 *) output) + height * width;
+			}
+			switch (opcode)
+			{
+				case 0:	/* Fill */
+					if (insertmix)
+					{
+						if (prevline == NULL)
+							line[x] = mix;
+						else
+							line[x] = prevline[x] ^ mix;
+						insertmix = False;
+						count--;
+						x++;
+					}
+					if (prevline == NULL)
+					{
+						REPEAT(line[x] = 0)
+					}
+					else
+					{
+						REPEAT(line[x] = prevline[x])
+					}
+					break;
+				case 1:	/* Mix */
+					if (prevline == NULL)
+					{
+						REPEAT(line[x] = mix)
+					}
+					else
+					{
+						REPEAT(line[x] = prevline[x] ^ mix)
+					}
+					break;
+				case 2:	/* Fill or Mix */
+					if (prevline == NULL)
+					{
+						REPEAT
+						(
+							MASK_UPDATE();
+							if (mask & mixmask)
+								line[x] = mix;
+							else
+								line[x] = 0;
+						)
+					}
+					else
+					{
+						REPEAT
+						(
+							MASK_UPDATE();
+							if (mask & mixmask)
+								line[x] = prevline[x] ^ mix;
+							else
+								line[x] = prevline[x];
+						)
+					}
+					break;
+				case 3:	/* Colour */
+					REPEAT(line[x] = colour2)
+					break;
+				case 4:	/* Copy */
+					REPEAT(CVAL2(input, line[x]))
+					break;
+				case 8:	/* Bicolour */
+					REPEAT
+					(
+						if (bicolour)
+						{
+							line[x] = colour2;
+							bicolour = False;
+						}
+						else
+						{
+							line[x] = colour1;
+							bicolour = True;
+							count++;
+						}
+					)
+					break;
+				case 0xd:	/* White */
+					REPEAT(line[x] = 0xffff)
+					break;
+				case 0xe:	/* Black */
+					REPEAT(line[x] = 0)
+					break;
+				default:
+					unimpl("bitmap opcode 0x%x\n", opcode);
+					return False;
+			}
+		}
+	}
+	return True;
+}
+
+/* 3 byte bitmap decompress */
+static RD_BOOL
+bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
+{
+	uint8 *end = input + size;
+	uint8 *prevline = NULL, *line = NULL;
+	int opcode, count, offset, isfillormix, x = width;
+	int lastopcode = -1, insertmix = False, bicolour = False;
+	uint8 code;
+	uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0};
+	uint8 mixmask, mask = 0;
+	uint8 mix[3] = {0xff, 0xff, 0xff};
+	int fom_mask = 0;
+
+	while (input < end)
+	{
+		fom_mask = 0;
+		code = CVAL(input);
+		opcode = code >> 4;
+		/* Handle different opcode forms */
+		switch (opcode)
+		{
+			case 0xc:
+			case 0xd:
+			case 0xe:
+				opcode -= 6;
+				count = code & 0xf;
+				offset = 16;
+				break;
+			case 0xf:
+				opcode = code & 0xf;
+				if (opcode < 9)
+				{
+					count = CVAL(input);
+					count |= CVAL(input) << 8;
+				}
+				else
+				{
+					count = (opcode <
+						 0xb) ? 8 : 1;
+				}
+				offset = 0;
+				break;
+			default:
+				opcode >>= 1;
+				count = code & 0x1f;
+				offset = 32;
+				break;
+		}
+		/* Handle strange cases for counts */
+		if (offset != 0)
+		{
+			isfillormix = ((opcode == 2) || (opcode == 7));
+			if (count == 0)
+			{
+				if (isfillormix)
+					count = CVAL(input) + 1;
+				else
+					count = CVAL(input) + offset;
+			}
+			else if (isfillormix)
+			{
+				count <<= 3;
+			}
+		}
+		/* Read preliminary data */
+		switch (opcode)
+		{
+			case 0:	/* Fill */
+				if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
+					insertmix = True;
+				break;
+			case 8:	/* Bicolour */
+				colour1[0] = CVAL(input);
+				colour1[1] = CVAL(input);
+				colour1[2] = CVAL(input);
+			case 3:	/* Colour */
+				colour2[0] = CVAL(input);
+				colour2[1] = CVAL(input);
+				colour2[2] = CVAL(input);
+				break;
+			case 6:	/* SetMix/Mix */
+			case 7:	/* SetMix/FillOrMix */
+				mix[0] = CVAL(input);
+				mix[1] = CVAL(input);
+				mix[2] = CVAL(input);
+				opcode -= 5;
+				break;
+			case 9:	/* FillOrMix_1 */
+				mask = 0x03;
+				opcode = 0x02;
+				fom_mask = 3;
+				break;
+			case 0x0a:	/* FillOrMix_2 */
+				mask = 0x05;
+				opcode = 0x02;
+				fom_mask = 5;
+				break;
+		}
+		lastopcode = opcode;
+		mixmask = 0;
+		/* Output body */
+		while (count > 0)
+		{
+			if (x >= width)
+			{
+				if (height <= 0)
+					return False;
+				x = 0;
+				height--;
+				prevline = line;
+				line = output + height * (width * 3);
+			}
+			switch (opcode)
+			{
+				case 0:	/* Fill */
+					if (insertmix)
+					{
+						if (prevline == NULL)
+						{
+							line[x * 3] = mix[0];
+							line[x * 3 + 1] = mix[1];
+							line[x * 3 + 2] = mix[2];
+						}
+						else
+						{
+							line[x * 3] =
+							 prevline[x * 3] ^ mix[0];
+							line[x * 3 + 1] =
+							 prevline[x * 3 + 1] ^ mix[1];
+							line[x * 3 + 2] =
+							 prevline[x * 3 + 2] ^ mix[2];
+						}
+						insertmix = False;
+						count--;
+						x++;
+					}
+					if (prevline == NULL)
+					{
+						REPEAT
+						(
+							line[x * 3] = 0;
+							line[x * 3 + 1] = 0;
+							line[x * 3 + 2] = 0;
+						)
+					}
+					else
+					{
+						REPEAT
+						(
+							line[x * 3] = prevline[x * 3];
+							line[x * 3 + 1] = prevline[x * 3 + 1];
+							line[x * 3 + 2] = prevline[x * 3 + 2];
+						)
+					}
+					break;
+				case 1:	/* Mix */
+					if (prevline == NULL)
+					{
+						REPEAT
+						(
+							line[x * 3] = mix[0];
+							line[x * 3 + 1] = mix[1];
+							line[x * 3 + 2] = mix[2];
+						)
+					}
+					else
+					{
+						REPEAT
+						(
+							line[x * 3] =
+							 prevline[x * 3] ^ mix[0];
+							line[x * 3 + 1] =
+							 prevline[x * 3 + 1] ^ mix[1];
+							line[x * 3 + 2] =
+							 prevline[x * 3 + 2] ^ mix[2];
+						)
+					}
+					break;
+				case 2:	/* Fill or Mix */
+					if (prevline == NULL)
+					{
+						REPEAT
+						(
+							MASK_UPDATE();
+							if (mask & mixmask)
+							{
+								line[x * 3] = mix[0];
+								line[x * 3 + 1] = mix[1];
+								line[x * 3 + 2] = mix[2];
+							}
+							else
+							{
+								line[x * 3] = 0;
+								line[x * 3 + 1] = 0;
+								line[x * 3 + 2] = 0;
+							}
+						)
+					}
+					else
+					{
+						REPEAT
+						(
+							MASK_UPDATE();
+							if (mask & mixmask)
+							{
+								line[x * 3] = 
+								 prevline[x * 3] ^ mix [0];
+								line[x * 3 + 1] =
+								 prevline[x * 3 + 1] ^ mix [1];
+								line[x * 3 + 2] =
+								 prevline[x * 3 + 2] ^ mix [2];
+							}
+							else
+							{
+								line[x * 3] =
+								 prevline[x * 3];
+								line[x * 3 + 1] =
+								 prevline[x * 3 + 1];
+								line[x * 3 + 2] =
+								 prevline[x * 3 + 2];
+							}
+						)
+					}
+					break;
+				case 3:	/* Colour */
+					REPEAT
+					(
+						line[x * 3] = colour2 [0];
+						line[x * 3 + 1] = colour2 [1];
+						line[x * 3 + 2] = colour2 [2];
+					)
+					break;
+				case 4:	/* Copy */
+					REPEAT
+					(
+						line[x * 3] = CVAL(input);
+						line[x * 3 + 1] = CVAL(input);
+						line[x * 3 + 2] = CVAL(input);
+					)
+					break;
+				case 8:	/* Bicolour */
+					REPEAT
+					(
+						if (bicolour)
+						{
+							line[x * 3] = colour2[0];
+							line[x * 3 + 1] = colour2[1];
+							line[x * 3 + 2] = colour2[2];
+							bicolour = False;
+						}
+						else
+						{
+							line[x * 3] = colour1[0];
+							line[x * 3 + 1] = colour1[1];
+							line[x * 3 + 2] = colour1[2];
+							bicolour = True;
+							count++;
+						}
+					)
+					break;
+				case 0xd:	/* White */
+					REPEAT
+					(
+						line[x * 3] = 0xff;
+						line[x * 3 + 1] = 0xff;
+						line[x * 3 + 2] = 0xff;
+					)
+					break;
+				case 0xe:	/* Black */
+					REPEAT
+					(
+						line[x * 3] = 0;
+						line[x * 3 + 1] = 0;
+						line[x * 3 + 2] = 0;
+					)
+					break;
+				default:
+					unimpl("bitmap opcode 0x%x\n", opcode);
+					return False;
+			}
+		}
+	}
+	return True;
+}
+
+/* decompress a colour plane */
+static int
+process_plane(uint8 * in, int width, int height, uint8 * out, int size)
+{
+	int indexw;
+	int indexh;
+	int code;
+	int collen;
+	int replen;
+	int color;
+	int x;
+	int revcode;
+	uint8 * last_line;
+	uint8 * this_line;
+	uint8 * org_in;
+	uint8 * org_out;
+
+	org_in = in;
+	org_out = out;
+	last_line = 0;
+	indexh = 0;
+	while (indexh < height)
+	{
+		out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
+		color = 0;
+		this_line = out;
+		indexw = 0;
+		if (last_line == 0)
+		{
+			while (indexw < width)
+			{
+				code = CVAL(in);
+				replen = code & 0xf;
+				collen = (code >> 4) & 0xf;
+				revcode = (replen << 4) | collen;
+				if ((revcode <= 47) && (revcode >= 16))
+				{
+					replen = revcode;
+					collen = 0;
+				}
+				while (collen > 0)
+				{
+					color = CVAL(in);
+					*out = color;
+					out += 4;
+					indexw++;
+					collen--;
+				}
+				while (replen > 0)
+				{
+					*out = color;
+					out += 4;
+					indexw++;
+					replen--;
+				}
+			}
+		}
+		else
+		{
+			while (indexw < width)
+			{
+				code = CVAL(in);
+				replen = code & 0xf;
+				collen = (code >> 4) & 0xf;
+				revcode = (replen << 4) | collen;
+				if ((revcode <= 47) && (revcode >= 16))
+				{
+					replen = revcode;
+					collen = 0;
+				}
+				while (collen > 0)
+				{
+					x = CVAL(in);
+					if (x & 1)
+					{
+						x = x >> 1;
+						x = x + 1;
+						color = -x;
+					}
+					else
+					{
+						x = x >> 1;
+						color = x;
+					}
+					x = last_line[indexw * 4] + color;
+					*out = x;
+					out += 4;
+					indexw++;
+					collen--;
+				}
+				while (replen > 0)
+				{
+					x = last_line[indexw * 4] + color;
+					*out = x;
+					out += 4;
+					indexw++;
+					replen--;
+				}
+			}
+		}
+		indexh++;
+		last_line = this_line;
+	}
+	return (int) (in - org_in);
+}
+
+/* 4 byte bitmap decompress */
+static RD_BOOL
+bitmap_decompress4(uint8 * output, int width, int height, uint8 * input, int size)
+{
+	int code;
+	int bytes_pro;
+	int total_pro;
+
+	code = CVAL(input);
+	if (code != 0x10)
+	{
+		return False;
+	}
+	total_pro = 1;
+	bytes_pro = process_plane(input, width, height, output + 3, size - total_pro);
+	total_pro += bytes_pro;
+	input += bytes_pro;
+	bytes_pro = process_plane(input, width, height, output + 2, size - total_pro);
+	total_pro += bytes_pro;
+	input += bytes_pro;
+	bytes_pro = process_plane(input, width, height, output + 1, size - total_pro);
+	total_pro += bytes_pro;
+	input += bytes_pro;
+	bytes_pro = process_plane(input, width, height, output + 0, size - total_pro);
+	total_pro += bytes_pro;
+	return size == total_pro;
+}
+
+/* main decompress function */
+RD_BOOL
+bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp)
+{
+	RD_BOOL rv = False;
+
+	switch (Bpp)
+	{
+		case 1:
+			rv = bitmap_decompress1(output, width, height, input, size);
+			break;
+		case 2:
+			rv = bitmap_decompress2(output, width, height, input, size);
+			break;
+		case 3:
+			rv = bitmap_decompress3(output, width, height, input, size);
+			break;
+		case 4:
+			rv = bitmap_decompress4(output, width, height, input, size);
+			break;
+		default:
+			unimpl("Bpp %d\n", Bpp);
+			break;
+	}
+	return rv;
+}
+
+/* *INDENT-ON* */
Index: /trunk/src/VBox/RDP/client-1.8.3/bootstrap
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/bootstrap	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/bootstrap	(revision 55121)
@@ -0,0 +1,3 @@
+#!/bin/sh
+rm -rf autom4te.cache
+autoreconf -i
Index: /trunk/src/VBox/RDP/client-1.8.3/cache.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/cache.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/cache.c	(revision 55121)
@@ -0,0 +1,473 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Cache routines
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright (C) Jeroen Meijer <jeroen@oldambt7.com> 2005
+   Copyright 2003-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+
+/* BITMAP CACHE */
+extern int g_pstcache_fd[];
+
+#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
+#define IS_PERSISTENT(id) (g_pstcache_fd[id] > 0)
+#define TO_TOP -1
+#define NOT_SET -1
+#define IS_SET(idx) (idx >= 0)
+
+/*
+ * TODO: Test for optimal value of BUMP_COUNT. TO_TOP gives lowest cpu utilisation but using
+ * a positive value will hopefully result in less frequently used bitmaps having a greater chance
+ * of being evicted from the cache, and therby reducing the need to load bitmaps from disk.
+ * (Jeroen)
+ */
+#define BUMP_COUNT 40
+
+struct bmpcache_entry
+{
+	RD_HBITMAP bitmap;
+	sint16 previous;
+	sint16 next;
+};
+
+static struct bmpcache_entry g_bmpcache[3][0xa00];
+static RD_HBITMAP g_volatile_bc[3];
+
+static int g_bmpcache_lru[3] = { NOT_SET, NOT_SET, NOT_SET };
+static int g_bmpcache_mru[3] = { NOT_SET, NOT_SET, NOT_SET };
+
+static int g_bmpcache_count[3];
+
+/* Setup the bitmap cache lru/mru linked list */
+void
+cache_rebuild_bmpcache_linked_list(uint8 id, sint16 * idx, int count)
+{
+	int n = count, c = 0;
+	sint16 n_idx;
+
+	/* find top, skip evicted bitmaps */
+	while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL);
+	if (n < 0)
+	{
+		g_bmpcache_mru[id] = g_bmpcache_lru[id] = NOT_SET;
+		return;
+	}
+
+	g_bmpcache_mru[id] = idx[n];
+	g_bmpcache[id][idx[n]].next = NOT_SET;
+	n_idx = idx[n];
+	c++;
+
+	/* link list */
+	while (n >= 0)
+	{
+		/* skip evicted bitmaps */
+		while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL);
+
+		if (n < 0)
+			break;
+
+		g_bmpcache[id][n_idx].previous = idx[n];
+		g_bmpcache[id][idx[n]].next = n_idx;
+		n_idx = idx[n];
+		c++;
+	}
+
+	g_bmpcache[id][n_idx].previous = NOT_SET;
+	g_bmpcache_lru[id] = n_idx;
+
+	if (c != g_bmpcache_count[id])
+	{
+		error("Oops. %d in bitmap cache linked list, %d in ui cache...\n", c,
+		      g_bmpcache_count[id]);
+		exit(EX_SOFTWARE);
+	}
+}
+
+/* Move a bitmap to a new position in the linked list. */
+void
+cache_bump_bitmap(uint8 id, uint16 idx, int bump)
+{
+	int p_idx, n_idx, n;
+
+	if (!IS_PERSISTENT(id))
+		return;
+
+	if (g_bmpcache_mru[id] == idx)
+		return;
+
+	DEBUG_RDP5(("bump bitmap: id=%d, idx=%d, bump=%d\n", id, idx, bump));
+
+	n_idx = g_bmpcache[id][idx].next;
+	p_idx = g_bmpcache[id][idx].previous;
+
+	if (IS_SET(n_idx))
+	{
+		/* remove */
+		--g_bmpcache_count[id];
+		if (IS_SET(p_idx))
+			g_bmpcache[id][p_idx].next = n_idx;
+		else
+			g_bmpcache_lru[id] = n_idx;
+		if (IS_SET(n_idx))
+			g_bmpcache[id][n_idx].previous = p_idx;
+		else
+			g_bmpcache_mru[id] = p_idx;
+	}
+	else
+	{
+		p_idx = NOT_SET;
+		n_idx = g_bmpcache_lru[id];
+	}
+
+	if (bump >= 0)
+	{
+		for (n = 0; n < bump && IS_SET(n_idx); n++)
+		{
+			p_idx = n_idx;
+			n_idx = g_bmpcache[id][p_idx].next;
+		}
+	}
+	else
+	{
+		p_idx = g_bmpcache_mru[id];
+		n_idx = NOT_SET;
+	}
+
+	/* insert */
+	++g_bmpcache_count[id];
+	g_bmpcache[id][idx].previous = p_idx;
+	g_bmpcache[id][idx].next = n_idx;
+
+	if (p_idx >= 0)
+		g_bmpcache[id][p_idx].next = idx;
+	else
+		g_bmpcache_lru[id] = idx;
+
+	if (n_idx >= 0)
+		g_bmpcache[id][n_idx].previous = idx;
+	else
+		g_bmpcache_mru[id] = idx;
+}
+
+/* Evict the least-recently used bitmap from the cache */
+void
+cache_evict_bitmap(uint8 id)
+{
+	uint16 idx;
+	int n_idx;
+
+	if (!IS_PERSISTENT(id))
+		return;
+
+	idx = g_bmpcache_lru[id];
+	n_idx = g_bmpcache[id][idx].next;
+	DEBUG_RDP5(("evict bitmap: id=%d idx=%d n_idx=%d bmp=%p\n", id, idx, n_idx,
+		    g_bmpcache[id][idx].bitmap));
+
+	ui_destroy_bitmap(g_bmpcache[id][idx].bitmap);
+	--g_bmpcache_count[id];
+	g_bmpcache[id][idx].bitmap = 0;
+
+	g_bmpcache_lru[id] = n_idx;
+	g_bmpcache[id][n_idx].previous = NOT_SET;
+
+	pstcache_touch_bitmap(id, idx, 0);
+}
+
+/* Retrieve a bitmap from the cache */
+RD_HBITMAP
+cache_get_bitmap(uint8 id, uint16 idx)
+{
+	if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0])))
+	{
+		if (g_bmpcache[id][idx].bitmap || pstcache_load_bitmap(id, idx))
+		{
+			if (IS_PERSISTENT(id))
+				cache_bump_bitmap(id, idx, BUMP_COUNT);
+
+			return g_bmpcache[id][idx].bitmap;
+		}
+	}
+	else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff))
+	{
+		return g_volatile_bc[id];
+	}
+
+	error("get bitmap %d:%d\n", id, idx);
+	return NULL;
+}
+
+/* Store a bitmap in the cache */
+void
+cache_put_bitmap(uint8 id, uint16 idx, RD_HBITMAP bitmap)
+{
+	RD_HBITMAP old;
+
+	if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0])))
+	{
+		old = g_bmpcache[id][idx].bitmap;
+		if (old != NULL)
+			ui_destroy_bitmap(old);
+		g_bmpcache[id][idx].bitmap = bitmap;
+
+		if (IS_PERSISTENT(id))
+		{
+			if (old == NULL)
+				g_bmpcache[id][idx].previous = g_bmpcache[id][idx].next = NOT_SET;
+
+			cache_bump_bitmap(id, idx, TO_TOP);
+			if (g_bmpcache_count[id] > BMPCACHE2_C2_CELLS)
+				cache_evict_bitmap(id);
+		}
+	}
+	else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff))
+	{
+		old = g_volatile_bc[id];
+		if (old != NULL)
+			ui_destroy_bitmap(old);
+		g_volatile_bc[id] = bitmap;
+	}
+	else
+	{
+		error("put bitmap %d:%d\n", id, idx);
+	}
+}
+
+/* Updates the persistent bitmap cache MRU information on exit */
+void
+cache_save_state(void)
+{
+	uint32 id = 0, t = 0;
+	int idx;
+
+	for (id = 0; id < NUM_ELEMENTS(g_bmpcache); id++)
+		if (IS_PERSISTENT(id))
+		{
+			DEBUG_RDP5(("Saving cache state for bitmap cache %d...", id));
+			idx = g_bmpcache_lru[id];
+			while (idx >= 0)
+			{
+				pstcache_touch_bitmap(id, idx, ++t);
+				idx = g_bmpcache[id][idx].next;
+			}
+			DEBUG_RDP5((" %d stamps written.\n", t));
+		}
+}
+
+
+/* FONT CACHE */
+static FONTGLYPH g_fontcache[12][256];
+
+/* Retrieve a glyph from the font cache */
+FONTGLYPH *
+cache_get_font(uint8 font, uint16 character)
+{
+	FONTGLYPH *glyph;
+
+	if ((font < NUM_ELEMENTS(g_fontcache)) && (character < NUM_ELEMENTS(g_fontcache[0])))
+	{
+		glyph = &g_fontcache[font][character];
+		if (glyph->pixmap != NULL)
+			return glyph;
+	}
+
+	error("get font %d:%d\n", font, character);
+	return NULL;
+}
+
+/* Store a glyph in the font cache */
+void
+cache_put_font(uint8 font, uint16 character, uint16 offset,
+	       uint16 baseline, uint16 width, uint16 height, RD_HGLYPH pixmap)
+{
+	FONTGLYPH *glyph;
+
+	if ((font < NUM_ELEMENTS(g_fontcache)) && (character < NUM_ELEMENTS(g_fontcache[0])))
+	{
+		glyph = &g_fontcache[font][character];
+		if (glyph->pixmap != NULL)
+			ui_destroy_glyph(glyph->pixmap);
+
+		glyph->offset = offset;
+		glyph->baseline = baseline;
+		glyph->width = width;
+		glyph->height = height;
+		glyph->pixmap = pixmap;
+	}
+	else
+	{
+		error("put font %d:%d\n", font, character);
+	}
+}
+
+
+/* TEXT CACHE */
+static DATABLOB g_textcache[256];
+
+/* Retrieve a text item from the cache */
+DATABLOB *
+cache_get_text(uint8 cache_id)
+{
+	DATABLOB *text;
+
+	text = &g_textcache[cache_id];
+	return text;
+}
+
+/* Store a text item in the cache */
+void
+cache_put_text(uint8 cache_id, void *data, int length)
+{
+	DATABLOB *text;
+
+	text = &g_textcache[cache_id];
+	if (text->data != NULL)
+		xfree(text->data);
+	text->data = xmalloc(length);
+	text->size = length;
+	memcpy(text->data, data, length);
+}
+
+
+/* DESKTOP CACHE */
+static uint8 g_deskcache[0x38400 * 4];
+
+/* Retrieve desktop data from the cache */
+uint8 *
+cache_get_desktop(uint32 offset, int cx, int cy, int bytes_per_pixel)
+{
+	int length = cx * cy * bytes_per_pixel;
+
+	if (offset > sizeof(g_deskcache))
+		offset = 0;
+
+	if ((offset + length) <= sizeof(g_deskcache))
+	{
+		return &g_deskcache[offset];
+	}
+
+	error("get desktop %d:%d\n", offset, length);
+	return NULL;
+}
+
+/* Store desktop data in the cache */
+void
+cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel, uint8 * data)
+{
+	int length = cx * cy * bytes_per_pixel;
+
+	if (offset > sizeof(g_deskcache))
+		offset = 0;
+
+	if ((offset + length) <= sizeof(g_deskcache))
+	{
+		cx *= bytes_per_pixel;
+		while (cy--)
+		{
+			memcpy(&g_deskcache[offset], data, cx);
+			data += scanline;
+			offset += cx;
+		}
+	}
+	else
+	{
+		error("put desktop %d:%d\n", offset, length);
+	}
+}
+
+
+/* CURSOR CACHE */
+static RD_HCURSOR g_cursorcache[0x20];
+
+/* Retrieve cursor from cache */
+RD_HCURSOR
+cache_get_cursor(uint16 cache_idx)
+{
+	RD_HCURSOR cursor;
+
+	if (cache_idx < NUM_ELEMENTS(g_cursorcache))
+	{
+		cursor = g_cursorcache[cache_idx];
+		if (cursor != NULL)
+			return cursor;
+	}
+
+	error("get cursor %d\n", cache_idx);
+	return NULL;
+}
+
+/* Store cursor in cache */
+void
+cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor)
+{
+	RD_HCURSOR old;
+
+	if (cache_idx < NUM_ELEMENTS(g_cursorcache))
+	{
+		old = g_cursorcache[cache_idx];
+		if (old != NULL)
+			ui_destroy_cursor(old);
+
+		g_cursorcache[cache_idx] = cursor;
+	}
+	else
+	{
+		error("put cursor %d\n", cache_idx);
+	}
+}
+
+/* BRUSH CACHE */
+/* index 0 is 2 colour brush, index 1 is muti colour brush */
+static BRUSHDATA g_brushcache[2][64];
+
+/* Retrieve brush from cache */
+BRUSHDATA *
+cache_get_brush_data(uint8 colour_code, uint8 idx)
+{
+	colour_code = colour_code == 1 ? 0 : 1;
+	if (idx < NUM_ELEMENTS(g_brushcache[0]))
+	{
+		return &g_brushcache[colour_code][idx];
+	}
+	error("get brush %d %d\n", colour_code, idx);
+	return NULL;
+}
+
+/* Store brush in cache */
+/* this function takes over the data pointer in struct, eg, caller gives it up */
+void
+cache_put_brush_data(uint8 colour_code, uint8 idx, BRUSHDATA * brush_data)
+{
+	BRUSHDATA *bd;
+
+	colour_code = colour_code == 1 ? 0 : 1;
+	if (idx < NUM_ELEMENTS(g_brushcache[0]))
+	{
+		bd = &g_brushcache[colour_code][idx];
+		if (bd->data != 0)
+		{
+			xfree(bd->data);
+		}
+		memcpy(bd, brush_data, sizeof(BRUSHDATA));
+	}
+	else
+	{
+		error("put brush %d %d\n", colour_code, idx);
+	}
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/channels.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/channels.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/channels.c	(revision 55121)
@@ -0,0 +1,188 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - Virtual channels
+   Copyright 2003 Erik Forsberg <forsberg@cendio.se> for Cendio AB
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+
+#define MAX_CHANNELS			6
+#define CHANNEL_CHUNK_LENGTH		1600
+#define CHANNEL_FLAG_FIRST		0x01
+#define CHANNEL_FLAG_LAST		0x02
+#define CHANNEL_FLAG_SHOW_PROTOCOL	0x10
+
+extern RDP_VERSION g_rdp_version;
+extern RD_BOOL g_encryption;
+
+VCHANNEL g_channels[MAX_CHANNELS];
+unsigned int g_num_channels;
+
+/* FIXME: We should use the information in TAG_SRV_CHANNELS to map RDP5
+   channels to MCS channels.
+
+   The format of TAG_SRV_CHANNELS seems to be
+
+   global_channel_no (uint16le)
+   number_of_other_channels (uint16le)
+   ..followed by uint16les for the other channels.
+*/
+
+VCHANNEL *
+channel_register(char *name, uint32 flags, void (*callback) (STREAM))
+{
+	VCHANNEL *channel;
+
+	if (g_rdp_version < RDP_V5)
+		return NULL;
+
+	if (g_num_channels >= MAX_CHANNELS)
+	{
+		error("Channel table full, increase MAX_CHANNELS\n");
+		return NULL;
+	}
+
+	channel = &g_channels[g_num_channels];
+	channel->mcs_id = MCS_GLOBAL_CHANNEL + 1 + g_num_channels;
+	strncpy(channel->name, name, 8);
+	channel->flags = flags;
+	channel->process = callback;
+	g_num_channels++;
+	return channel;
+}
+
+STREAM
+channel_init(VCHANNEL * channel, uint32 length)
+{
+	STREAM s;
+
+	s = sec_init(g_encryption ? SEC_ENCRYPT : 0, length + 8);
+	s_push_layer(s, channel_hdr, 8);
+	return s;
+}
+
+void
+channel_send(STREAM s, VCHANNEL * channel)
+{
+	uint32 length, flags;
+	uint32 thislength, remaining;
+	uint8 *data;
+
+#ifdef WITH_SCARD
+	scard_lock(SCARD_LOCK_CHANNEL);
+#endif
+
+	/* first fragment sent in-place */
+	s_pop_layer(s, channel_hdr);
+	length = s->end - s->p - 8;
+
+	DEBUG_CHANNEL(("channel_send, length = %d\n", length));
+
+	thislength = MIN(length, CHANNEL_CHUNK_LENGTH);
+/* Note: In the original clipboard implementation, this number was
+   1592, not 1600. However, I don't remember the reason and 1600 seems
+   to work so.. This applies only to *this* length, not the length of
+   continuation or ending packets. */
+	remaining = length - thislength;
+	flags = (remaining == 0) ? CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST : CHANNEL_FLAG_FIRST;
+	if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL)
+		flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
+
+	out_uint32_le(s, length);
+	out_uint32_le(s, flags);
+	data = s->end = s->p + thislength;
+	DEBUG_CHANNEL(("Sending %d bytes with FLAG_FIRST\n", thislength));
+	sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id);
+
+	/* subsequent segments copied (otherwise would have to generate headers backwards) */
+	while (remaining > 0)
+	{
+		thislength = MIN(remaining, CHANNEL_CHUNK_LENGTH);
+		remaining -= thislength;
+		flags = (remaining == 0) ? CHANNEL_FLAG_LAST : 0;
+		if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL)
+			flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
+
+		DEBUG_CHANNEL(("Sending %d bytes with flags %d\n", thislength, flags));
+
+		s = sec_init(g_encryption ? SEC_ENCRYPT : 0, thislength + 8);
+		out_uint32_le(s, length);
+		out_uint32_le(s, flags);
+		out_uint8p(s, data, thislength);
+		s_mark_end(s);
+		sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id);
+
+		data += thislength;
+	}
+
+#ifdef WITH_SCARD
+	scard_unlock(SCARD_LOCK_CHANNEL);
+#endif
+}
+
+void
+channel_process(STREAM s, uint16 mcs_channel)
+{
+	uint32 length, flags;
+	uint32 thislength;
+	VCHANNEL *channel = NULL;
+	unsigned int i;
+	STREAM in;
+
+	for (i = 0; i < g_num_channels; i++)
+	{
+		channel = &g_channels[i];
+		if (channel->mcs_id == mcs_channel)
+			break;
+	}
+
+	if (i >= g_num_channels)
+		return;
+
+	in_uint32_le(s, length);
+	in_uint32_le(s, flags);
+	if ((flags & CHANNEL_FLAG_FIRST) && (flags & CHANNEL_FLAG_LAST))
+	{
+		/* single fragment - pass straight up */
+		channel->process(s);
+	}
+	else
+	{
+		/* add fragment to defragmentation buffer */
+		in = &channel->in;
+		if (flags & CHANNEL_FLAG_FIRST)
+		{
+			if (length > in->size)
+			{
+				in->data = (uint8 *) xrealloc(in->data, length);
+				in->size = length;
+			}
+			in->p = in->data;
+		}
+
+		thislength = MIN(s->end - s->p, in->data + in->size - in->p);
+		memcpy(in->p, s->p, thislength);
+		in->p += thislength;
+
+		if (flags & CHANNEL_FLAG_LAST)
+		{
+			in->end = in->p;
+			in->p = in->data;
+			channel->process(in);
+		}
+	}
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/cliprdr.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/cliprdr.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/cliprdr.c	(revision 55121)
@@ -0,0 +1,186 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - Clipboard functions
+   Copyright 2003 Erik Forsberg <forsberg@cendio.se> for Cendio AB
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+
+#define CLIPRDR_CONNECT			1
+#define CLIPRDR_FORMAT_ANNOUNCE		2
+#define CLIPRDR_FORMAT_ACK		3
+#define CLIPRDR_DATA_REQUEST		4
+#define CLIPRDR_DATA_RESPONSE		5
+
+#define CLIPRDR_REQUEST			0
+#define CLIPRDR_RESPONSE		1
+#define CLIPRDR_ERROR			2
+
+static VCHANNEL *cliprdr_channel;
+
+static uint8 *last_formats = NULL;
+static uint32 last_formats_length = 0;
+
+static void
+cliprdr_send_packet(uint16 type, uint16 status, uint8 * data, uint32 length)
+{
+	STREAM s;
+
+	DEBUG_CLIPBOARD(("CLIPRDR send: type=%d, status=%d, length=%d\n", type, status, length));
+
+	s = channel_init(cliprdr_channel, length + 12);
+	out_uint16_le(s, type);
+	out_uint16_le(s, status);
+	out_uint32_le(s, length);
+	out_uint8p(s, data, length);
+	out_uint32(s, 0);	/* pad? */
+	s_mark_end(s);
+	channel_send(s, cliprdr_channel);
+}
+
+/* Helper which announces our readiness to supply clipboard data
+   in a single format (such as CF_TEXT) to the RDP side.
+   To announce more than one format at a time, use
+   cliprdr_send_native_format_announce.
+ */
+void
+cliprdr_send_simple_native_format_announce(uint32 format)
+{
+	uint8 buffer[36];
+
+	DEBUG_CLIPBOARD(("cliprdr_send_simple_native_format_announce\n"));
+
+	buf_out_uint32(buffer, format);
+	memset(buffer + 4, 0, sizeof(buffer) - 4);	/* description */
+	cliprdr_send_native_format_announce(buffer, sizeof(buffer));
+}
+
+/* Announces our readiness to supply clipboard data in multiple
+   formats, each denoted by a 36-byte format descriptor of
+   [ uint32 format + 32-byte description ].
+ */
+void
+cliprdr_send_native_format_announce(uint8 * formats_data, uint32 formats_data_length)
+{
+	DEBUG_CLIPBOARD(("cliprdr_send_native_format_announce\n"));
+
+	cliprdr_send_packet(CLIPRDR_FORMAT_ANNOUNCE, CLIPRDR_REQUEST, formats_data,
+			    formats_data_length);
+
+	if (formats_data != last_formats)
+	{
+		if (last_formats)
+			xfree(last_formats);
+
+		last_formats = xmalloc(formats_data_length);
+		memcpy(last_formats, formats_data, formats_data_length);
+		last_formats_length = formats_data_length;
+	}
+}
+
+void
+cliprdr_send_data_request(uint32 format)
+{
+	uint8 buffer[4];
+
+	DEBUG_CLIPBOARD(("cliprdr_send_data_request\n"));
+	buf_out_uint32(buffer, format);
+	cliprdr_send_packet(CLIPRDR_DATA_REQUEST, CLIPRDR_REQUEST, buffer, sizeof(buffer));
+}
+
+void
+cliprdr_send_data(uint8 * data, uint32 length)
+{
+	DEBUG_CLIPBOARD(("cliprdr_send_data\n"));
+	cliprdr_send_packet(CLIPRDR_DATA_RESPONSE, CLIPRDR_RESPONSE, data, length);
+}
+
+static void
+cliprdr_process(STREAM s)
+{
+	uint16 type, status;
+	uint32 length, format;
+	uint8 *data;
+
+	in_uint16_le(s, type);
+	in_uint16_le(s, status);
+	in_uint32_le(s, length);
+	data = s->p;
+
+	DEBUG_CLIPBOARD(("CLIPRDR recv: type=%d, status=%d, length=%d\n", type, status, length));
+
+	if (status == CLIPRDR_ERROR)
+	{
+		switch (type)
+		{
+			case CLIPRDR_FORMAT_ACK:
+				/* FIXME: We seem to get this when we send an announce while the server is
+				   still processing a paste. Try sending another announce. */
+				cliprdr_send_native_format_announce(last_formats,
+								    last_formats_length);
+				break;
+			case CLIPRDR_DATA_RESPONSE:
+				ui_clip_request_failed();
+				break;
+			default:
+				DEBUG_CLIPBOARD(("CLIPRDR error (type=%d)\n", type));
+		}
+
+		return;
+	}
+
+	switch (type)
+	{
+		case CLIPRDR_CONNECT:
+			ui_clip_sync();
+			break;
+		case CLIPRDR_FORMAT_ANNOUNCE:
+			ui_clip_format_announce(data, length);
+			cliprdr_send_packet(CLIPRDR_FORMAT_ACK, CLIPRDR_RESPONSE, NULL, 0);
+			return;
+		case CLIPRDR_FORMAT_ACK:
+			break;
+		case CLIPRDR_DATA_REQUEST:
+			in_uint32_le(s, format);
+			ui_clip_request_data(format);
+			break;
+		case CLIPRDR_DATA_RESPONSE:
+			ui_clip_handle_data(data, length);
+			break;
+		case 7:	/* TODO: W2K3 SP1 sends this on connect with a value of 1 */
+			break;
+		default:
+			unimpl("CLIPRDR packet type %d\n", type);
+	}
+}
+
+void
+cliprdr_set_mode(const char *optarg)
+{
+	ui_clip_set_mode(optarg);
+}
+
+RD_BOOL
+cliprdr_init(void)
+{
+	cliprdr_channel =
+		channel_register("cliprdr",
+				 CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
+				 CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL,
+				 cliprdr_process);
+	return (cliprdr_channel != NULL);
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/config.guess
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/config.guess	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/config.guess	(revision 55121)
@@ -0,0 +1,1411 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-06-17'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+## for Red Hat Linux
+if test -f /etc/redhat-release ; then
+    VENDOR=redhat ;
+else
+    VENDOR= ;
+fi
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently, or will in the future.
+	case "${UNAME_MACHINE_ARCH}" in
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep __ELF__ >/dev/null
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+	        os=netbsd
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}"
+	exit 0 ;;
+    amiga:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    arc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    hp300:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mac68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    macppc:OpenBSD:*:*)
+	echo powerpc-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+	echo m88k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    mvmeppc:OpenBSD:*:*)
+	echo powerpc-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    pmax:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sgi:OpenBSD:*:*)
+	echo mipseb-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    sun3:OpenBSD:*:*)
+	echo m68k-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+	echo mipsel-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    *:OpenBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+	exit 0 ;;
+    alpha:OSF1:*:*)
+	if test $UNAME_RELEASE = "V4.0"; then
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+	fi
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE="alpha" ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE="alpha" ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE="alphaev5" ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE="alphaev56" ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE="alphapca56" ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE="alphapca57" ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE="alphaev6" ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE="alphaev67" ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE="alphaev68" ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE="alphaev69" ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE="alphaev7" ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE="alphaev79" ;;
+	esac
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+	exit 0 ;;
+    Alpha*:OpenVMS:*:*)
+	echo alpha-hp-vms
+	exit 0 ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit 0 ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit 0;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit 0 ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit 0 ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit 0 ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit 0 ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit 0 ;;
+    DRS?6000:UNIX_SV:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7 && exit 0 ;;
+	esac ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    i86pc:SunOS:5.*:*)
+	echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit 0 ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit 0 ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit 0 ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+	exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit 0 ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit 0 ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c \
+	  && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+	  && exit 0
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit 0 ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit 0 ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit 0 ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit 0 ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit 0 ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+ 	exit 0 ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit 0 ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit 0 ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+	exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit 0 ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+		echo rs6000-ibm-aix3.2.5
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit 0 ;;
+    *:AIX:*:[45])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit 0 ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+              	{
+              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+              	case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+              	    switch (bits)
+              		{
+              		case 64: puts ("hppa2.0w"); break;
+              		case 32: puts ("hppa2.0n"); break;
+              		default: puts ("hppa2.0"); break;
+              		} break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+              	    puts ("hppa2.0"); break;
+              #endif
+              	default: puts ("hppa1.0"); break;
+              	}
+                  exit (0);
+              }
+EOF
+		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = "hppa2.0w" ]
+	then
+	    # avoid double evaluation of $set_cc_for_build
+	    test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+	    then
+		HP_ARCH="hppa2.0w"
+	    else
+		HP_ARCH="hppa64"
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit 0 ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+	echo unknown-hitachi-hiuxwe2
+	exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit 0 ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit 0 ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit 0 ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit 0 ;;
+    *:UNICOS/mp:*:*)
+	echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' 
+	exit 0 ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit 0 ;;
+    *:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
+	# Determine whether the default compiler uses glibc.
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#if __GLIBC__ >= 2
+	LIBC=gnu
+	#else
+	LIBC=
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+	echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+	exit 0 ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit 0 ;;
+    i*:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit 0 ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit 0 ;;
+    x86:Interix*:[34]*)
+	echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+	exit 0 ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit 0 ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit 0 ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit 0 ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit 0 ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit 0 ;;
+    *:GNU:*:*)
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit 0 ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit 0 ;;
+    arm*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    cris:Linux:*:*)
+	echo cris-axis-linux-gnu
+	exit 0 ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-${VENDOR:-unknown}-linux-gnu
+	exit 0 ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    mips:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips
+	#undef mipsel
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mipsel
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+	;;
+    mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef mips64
+	#undef mips64el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=mips64el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=mips64
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+	test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+	;;
+    ppc:Linux:*:*)
+	echo powerpc-${VENDOR:-unknown}-linux-gnu
+	exit 0 ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-${VENDOR:-unknown}-linux-gnu
+	exit 0 ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+	objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+	exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-gnu ;;
+	  PA8*) echo hppa2.0-unknown-linux-gnu ;;
+	  *)    echo hppa-unknown-linux-gnu ;;
+	esac
+	exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-gnu
+	exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-${VENDOR:-ibm}-linux-gnu
+	exit 0 ;;
+    sh64*:Linux:*:*)
+    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit 0 ;;
+    x86_64:Linux:*:*)
+	echo x86_64-${VENDOR:-unknown}-linux-gnu
+	exit 0 ;;
+    i*86:Linux:*:*)
+	# The BFD linker knows what the default object file format is, so
+	# first see if it will tell us. cd to the root directory to prevent
+	# problems with other programs or directories called `ld' in the path.
+	# Set LC_ALL=C to ensure ld outputs messages in English.
+	ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+			 | sed -ne '/supported targets:/!d
+				    s/[ 	][ 	]*/ /g
+				    s/.*supported targets: *//
+				    s/ .*//
+				    p'`
+        case "$ld_supported_targets" in
+	  elf32-i386)
+		TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+		;;
+	  a.out-i386-linux)
+		echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+		exit 0 ;;
+	  coff-i386)
+		echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+		exit 0 ;;
+	  "")
+		# Either a pre-BFD a.out linker (linux-gnuoldld) or
+		# one that does not give us useful --help.
+		echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+		exit 0 ;;
+	esac
+	# Determine whether the default compiler is a.out or elf
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <features.h>
+	#ifdef __ELF__
+	# ifdef __GLIBC__
+	#  if __GLIBC__ >= 2
+	LIBC=gnu
+	#  else
+	LIBC=gnulibc1
+	#  endif
+	# else
+	LIBC=gnulibc1
+	# endif
+	#else
+	#ifdef __INTEL_COMPILER
+	LIBC=gnu
+	#else
+	LIBC=gnuaout
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+	test x"${LIBC}" != x && echo "${UNAME_MACHINE}-${VENDOR:-pc}-linux-${LIBC}" && exit 0
+	test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+	;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit 0 ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit 0 ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit 0 ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit 0 ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit 0 ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit 0 ;;
+    i*86:*:5:[78]*)
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit 0 ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit 0 ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+	echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit 0 ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit 0 ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit 0 ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit 0 ;;
+    M68*:*:R3V[567]*:*)
+	test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit 0 ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit 0 ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit 0 ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit 0 ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit 0 ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit 0 ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit 0 ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+	        echo mips-nec-sysv${UNAME_RELEASE}
+	else
+	        echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit 0 ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit 0 ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit 0 ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit 0 ;;
+    *:Darwin:*:*)
+	case `uname -p` in
+	    *86) UNAME_PROCESSOR=i686 ;;
+	    powerpc) UNAME_PROCESSOR=powerpc ;;
+	esac
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = "x86"; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit 0 ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit 0 ;;
+    NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit 0 ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit 0 ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit 0 ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = "386"; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit 0 ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit 0 ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit 0 ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit 0 ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit 0 ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+	exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+	  ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+	printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+	printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+	echo c1-convex-bsd
+	exit 0 ;;
+    c2*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit 0 ;;
+    c34*)
+	echo c34-convex-bsd
+	exit 0 ;;
+    c38*)
+	echo c38-convex-bsd
+	exit 0 ;;
+    c4*)
+	echo c4-convex-bsd
+	exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /trunk/src/VBox/RDP/client-1.8.3/config.sub
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/config.sub	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/config.sub	(revision 55121)
@@ -0,0 +1,1500 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2003-06-18'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis)
+		os=
+		basic_machine=$1
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+ 	-chorusrdb)
+ 		os=-chorusrdb
+		basic_machine=$1
+ 		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+	| c4x | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| fr30 | frv \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| i370 | i860 | i960 | ia64 \
+	| ip2k \
+	| m32r | m68000 | m68k | m88k | mcore \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64vr | mips64vrel \
+	| mips64orion | mips64orionel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| msp430 \
+	| ns16k | ns32k \
+	| openrisc | or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| pyramid \
+	| s390 | s390x \
+	| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+	| strongarm \
+	| tahoe | thumb | tic4x | tic80 | tron \
+	| v850 | v850e \
+	| we32k \
+	| x86 | xscale | xstormy16 | xtensa \
+	| z8k)
+		basic_machine=$basic_machine-unknown
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12)
+		# Motorola 68HC11/12.
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* \
+	| bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| clipper-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| elxsi-* \
+	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| i*86-* | i860-* | i960-* | ia64-* \
+	| ip2k-* \
+	| m32r-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | mcore-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipstx39-* | mipstx39el-* \
+	| msp430-* \
+	| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| pyramid-* \
+	| romp-* | rs6000-* \
+	| s390-* | s390x-* \
+	| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+	| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+	| tahoe-* | thumb-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tron-* \
+	| v850-* | v850e-* | vax-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+	| xtensa-* \
+	| ymp-* \
+	| z8k-*)
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	mingw32)
+		basic_machine=i386-pc
+		os=-mingw32
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	mmix*)
+		basic_machine=mmix-knuth
+		os=-mmixware
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	nv1)
+		basic_machine=nv1-cray
+		os=-unicosmp
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	or32 | or32-*)
+		basic_machine=or32-unknown
+		os=-coff
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc)	basic_machine=powerpc-unknown
+		;;
+	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle | ppc-le | powerpc-little)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tic54x | c54x*)
+		basic_machine=tic54x-unknown
+		os=-coff
+		;;
+	tic55x | c55x*)
+		basic_machine=tic55x-unknown
+		os=-coff
+		;;
+	tic6x | c6x*)
+		basic_machine=tic6x-unknown
+		os=-coff
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparc | sparcv9 | sparcv9b)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+	      | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* \
+	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-kaos*)
+		os=-kaos
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		# This also exists in the configure program, but was not the
+		# default.
+		# os=-sunos4
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
Index: /trunk/src/VBox/RDP/client-1.8.3/configure
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/configure	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/configure	(revision 55121)
@@ -0,0 +1,8652 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for rdesktop 1.8.3.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='rdesktop'
+PACKAGE_TARNAME='rdesktop'
+PACKAGE_VERSION='1.8.3'
+PACKAGE_STRING='rdesktop 1.8.3'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="rdesktop.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBICONV
+LIBOBJS
+SOUNDOBJ
+LIBSAMPLERATE_LIBS
+LIBSAMPLERATE_CFLAGS
+ALSA_LIBS
+ALSA_CFLAGS
+LIBAO_LIBS
+LIBAO_CFLAGS
+RDP2VNCTARGET
+VNCLINK
+LDVNC
+VNCINC
+SCARDOBJ
+PCSCLITE_LIBS
+PCSCLITE_CFLAGS
+XRANDR_LIBS
+XRANDR_CFLAGS
+CREDSSPOBJ
+GSSGLUE_LIBS
+GSSGLUE_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+ssldir
+STRIP
+PKG_CONFIG
+X_EXTRA_LIBS
+X_LIBS
+X_PRE_LIBS
+X_CFLAGS
+XMKMF
+EGREP
+GREP
+CPP
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_x
+with_openssl
+enable_static_openssl
+enable_credssp
+enable_static_gssglue
+enable_smartcard
+with_egd_socket
+with_libvncserver_config
+with_libvncserver
+with_sound
+enable_static_libsamplerate
+with_libiconv_prefix
+enable_largefile
+with_ipv6
+with_debug
+with_debug_kbd
+with_debug_rdp5
+with_debug_clipboard
+with_debug_sound
+with_debug_channel
+with_debug_seamless
+with_debug_smartcard
+with_debug_credssp
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+XMKMF
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+GSSGLUE_CFLAGS
+GSSGLUE_LIBS
+XRANDR_CFLAGS
+XRANDR_LIBS
+PCSCLITE_CFLAGS
+PCSCLITE_LIBS
+LIBAO_CFLAGS
+LIBAO_LIBS
+ALSA_CFLAGS
+ALSA_LIBS
+LIBSAMPLERATE_CFLAGS
+LIBSAMPLERATE_LIBS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures rdesktop 1.8.3 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/rdesktop]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+X features:
+  --x-includes=DIR    X include files are in DIR
+  --x-libraries=DIR   X library files are in DIR
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of rdesktop 1.8.3:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-static-openssl link OpenSSL statically
+  --disable-credssp       disable support for CredSSP
+  --enable-static-gssglue
+  --disable-smartcard     disable support for smartcard
+  --enable-static-libsamplerate link libsamplerate statically
+  --disable-largefile     omit support for large files
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-x                use the X Window System
+  --with-openssl=DIR          look for OpenSSL at DIR/include, DIR/lib
+  --with-egd-socket=PATH  look for Entropy Gathering Daemon socket at PATH
+  --with-libvncserver-config=CMD  use CMD as libvncserver-config
+  --with-libvncserver     make rdp2vnc
+  --with-sound            select sound system ("oss", "sgi", "sun", "alsa" or "libao")
+  --with-libiconv-prefix=DIR  search for libiconv in DIR/include and DIR/lib
+  --with-ipv6             enable IPv6-support
+  --with-debug            enable protocol debugging output
+  --with-debug-kbd        enable debugging of keyboard handling
+  --with-debug-rdp5       enable debugging of RDP5 code
+  --with-debug-clipboard  enable debugging of clipboard code
+  --with-debug-sound  enable debugging of sound code
+  --with-debug-channel  enable debugging of virtual channel code
+  --with-debug-seamless  enable debugging of SeamlessRDP code
+  --with-debug-smartcard  enable debugging of smart-card code
+  --with-debug-credssp	enable debugging of CredSSP code
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+  XMKMF       Path to xmkmf, Makefile generator for X Window System
+  PKG_CONFIG  path to pkg-config utility
+  PKG_CONFIG_PATH
+              directories to add to pkg-config's search path
+  PKG_CONFIG_LIBDIR
+              path overriding pkg-config's built-in search path
+  GSSGLUE_CFLAGS
+              C compiler flags for GSSGLUE, overriding pkg-config
+  GSSGLUE_LIBS
+              linker flags for GSSGLUE, overriding pkg-config
+  XRANDR_CFLAGS
+              C compiler flags for XRANDR, overriding pkg-config
+  XRANDR_LIBS linker flags for XRANDR, overriding pkg-config
+  PCSCLITE_CFLAGS
+              C compiler flags for PCSCLITE, overriding pkg-config
+  PCSCLITE_LIBS
+              linker flags for PCSCLITE, overriding pkg-config
+  LIBAO_CFLAGS
+              C compiler flags for LIBAO, overriding pkg-config
+  LIBAO_LIBS  linker flags for LIBAO, overriding pkg-config
+  ALSA_CFLAGS C compiler flags for ALSA, overriding pkg-config
+  ALSA_LIBS   linker flags for ALSA, overriding pkg-config
+  LIBSAMPLERATE_CFLAGS
+              C compiler flags for LIBSAMPLERATE, overriding pkg-config
+  LIBSAMPLERATE_LIBS
+              linker flags for LIBSAMPLERATE, overriding pkg-config
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+rdesktop configure 1.8.3
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+	 return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+	    return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by rdesktop $as_me 1.8.3, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test "$GCC" = yes; then
+    CFLAGS="$CFLAGS -Wall"
+fi
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_bigendian=unknown
+    # See if we're dealing with a universal compiler.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __APPLE_CC__
+	       not a universal capable compiler
+	     #endif
+	     typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+	# Check for potential -arch flags.  It is not universal unless
+	# there are at least two -arch flags with different values.
+	ac_arch=
+	ac_prev=
+	for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+	 if test -n "$ac_prev"; then
+	   case $ac_word in
+	     i?86 | x86_64 | ppc | ppc64)
+	       if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+		 ac_arch=$ac_word
+	       else
+		 ac_cv_c_bigendian=universal
+		 break
+	       fi
+	       ;;
+	   esac
+	   ac_prev=
+	 elif test "x$ac_word" = "x-arch"; then
+	   ac_prev=arch
+	 fi
+       done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if sys/param.h defines the BYTE_ORDER macro.
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+	     #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+		     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+		     && LITTLE_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+		#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to _BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_bigendian=yes
+else
+  ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    fi
+    if test $ac_cv_c_bigendian = unknown; then
+      # Compile a test program.
+      if test "$cross_compiling" = yes; then :
+  # Try to guess by grepping values from an object file.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+short int ascii_mm[] =
+		  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+		short int ascii_ii[] =
+		  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+		int use_ascii (int i) {
+		  return ascii_mm[i] + ascii_ii[i];
+		}
+		short int ebcdic_ii[] =
+		  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+		short int ebcdic_mm[] =
+		  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+		int use_ebcdic (int i) {
+		  return ebcdic_mm[i] + ebcdic_ii[i];
+		}
+		extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+	      ac_cv_c_bigendian=yes
+	    fi
+	    if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+	      if test "$ac_cv_c_bigendian" = unknown; then
+		ac_cv_c_bigendian=no
+	      else
+		# finding both strings is unlikely to happen, but who knows?
+		ac_cv_c_bigendian=unknown
+	      fi
+	    fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+	     /* Are we little or big endian?  From Harbison&Steele.  */
+	     union
+	     {
+	       long int l;
+	       char c[sizeof (long int)];
+	     } u;
+	     u.l = 1;
+	     return u.c[sizeof (long int) - 1] == 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_bigendian=no
+else
+  ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+   yes)
+     $as_echo "#define B_ENDIAN 1" >>confdefs.h
+;; #(
+   no)
+     $as_echo "#define L_ENDIAN 1" >>confdefs.h
+ ;; #(
+   universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+     ;; #(
+   *)
+     as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5
+$as_echo_n "checking for X... " >&6; }
+
+
+# Check whether --with-x was given.
+if test "${with_x+set}" = set; then :
+  withval=$with_x;
+fi
+
+# $have_x is `yes', `no', `disabled', or empty when we do not yet know.
+if test "x$with_x" = xno; then
+  # The user explicitly disabled X.
+  have_x=disabled
+else
+  case $x_includes,$x_libraries in #(
+    *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #(
+    *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # One or both of the vars are not set, and there is no cached value.
+ac_x_includes=no ac_x_libraries=no
+rm -f -r conftest.dir
+if mkdir conftest.dir; then
+  cd conftest.dir
+  cat >Imakefile <<'_ACEOF'
+incroot:
+	@echo incroot='${INCROOT}'
+usrlibdir:
+	@echo usrlibdir='${USRLIBDIR}'
+libdir:
+	@echo libdir='${LIBDIR}'
+_ACEOF
+  if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then
+    # GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+    for ac_var in incroot usrlibdir libdir; do
+      eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`"
+    done
+    # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+    for ac_extension in a so sl dylib la dll; do
+      if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" &&
+	 test -f "$ac_im_libdir/libX11.$ac_extension"; then
+	ac_im_usrlibdir=$ac_im_libdir; break
+      fi
+    done
+    # Screen out bogus values from the imake configuration.  They are
+    # bogus both because they are the default anyway, and because
+    # using them would break gcc on systems where it needs fixed includes.
+    case $ac_im_incroot in
+	/usr/include) ac_x_includes= ;;
+	*) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;;
+    esac
+    case $ac_im_usrlibdir in
+	/usr/lib | /usr/lib64 | /lib | /lib64) ;;
+	*) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;;
+    esac
+  fi
+  cd ..
+  rm -f -r conftest.dir
+fi
+
+# Standard set of common directories for X headers.
+# Check X11 before X11Rn because it is often a symlink to the current release.
+ac_x_header_dirs='
+/usr/X11/include
+/usr/X11R7/include
+/usr/X11R6/include
+/usr/X11R5/include
+/usr/X11R4/include
+
+/usr/include/X11
+/usr/include/X11R7
+/usr/include/X11R6
+/usr/include/X11R5
+/usr/include/X11R4
+
+/usr/local/X11/include
+/usr/local/X11R7/include
+/usr/local/X11R6/include
+/usr/local/X11R5/include
+/usr/local/X11R4/include
+
+/usr/local/include/X11
+/usr/local/include/X11R7
+/usr/local/include/X11R6
+/usr/local/include/X11R5
+/usr/local/include/X11R4
+
+/usr/X386/include
+/usr/x386/include
+/usr/XFree86/include/X11
+
+/usr/include
+/usr/local/include
+/usr/unsupported/include
+/usr/athena/include
+/usr/local/x11r5/include
+/usr/lpp/Xamples/include
+
+/usr/openwin/include
+/usr/openwin/share/include'
+
+if test "$ac_x_includes" = no; then
+  # Guess where to find include files, by looking for Xlib.h.
+  # First, try using that file with no special directory specified.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <X11/Xlib.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # We can compile using X headers with no special include directory.
+ac_x_includes=
+else
+  for ac_dir in $ac_x_header_dirs; do
+  if test -r "$ac_dir/X11/Xlib.h"; then
+    ac_x_includes=$ac_dir
+    break
+  fi
+done
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+fi # $ac_x_includes = no
+
+if test "$ac_x_libraries" = no; then
+  # Check for the libraries.
+  # See if we find them without any special options.
+  # Don't add to $LIBS permanently.
+  ac_save_LIBS=$LIBS
+  LIBS="-lX11 $LIBS"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <X11/Xlib.h>
+int
+main ()
+{
+XrmInitialize ()
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  LIBS=$ac_save_LIBS
+# We can link X programs with no special library path.
+ac_x_libraries=
+else
+  LIBS=$ac_save_LIBS
+for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g`
+do
+  # Don't even attempt the hair of trying to link an X program!
+  for ac_extension in a so sl dylib la dll; do
+    if test -r "$ac_dir/libX11.$ac_extension"; then
+      ac_x_libraries=$ac_dir
+      break 2
+    fi
+  done
+done
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi # $ac_x_libraries = no
+
+case $ac_x_includes,$ac_x_libraries in #(
+  no,* | *,no | *\'*)
+    # Didn't find X, or a directory has "'" in its name.
+    ac_cv_have_x="have_x=no";; #(
+  *)
+    # Record where we found X for the cache.
+    ac_cv_have_x="have_x=yes\
+	ac_x_includes='$ac_x_includes'\
+	ac_x_libraries='$ac_x_libraries'"
+esac
+fi
+;; #(
+    *) have_x=yes;;
+  esac
+  eval "$ac_cv_have_x"
+fi # $with_x != no
+
+if test "$have_x" != yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5
+$as_echo "$have_x" >&6; }
+  no_x=yes
+else
+  # If each of the values was on the command line, it overrides each guess.
+  test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+  test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+  # Update the cache value to reflect the command line values.
+  ac_cv_have_x="have_x=yes\
+	ac_x_includes='$x_includes'\
+	ac_x_libraries='$x_libraries'"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5
+$as_echo "libraries $x_libraries, headers $x_includes" >&6; }
+fi
+
+if test "$no_x" = yes; then
+  # Not all programs may use this symbol, but it does not hurt to define it.
+
+$as_echo "#define X_DISPLAY_MISSING 1" >>confdefs.h
+
+  X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS=
+else
+  if test -n "$x_includes"; then
+    X_CFLAGS="$X_CFLAGS -I$x_includes"
+  fi
+
+  # It would also be nice to do this for all -L options, not just this one.
+  if test -n "$x_libraries"; then
+    X_LIBS="$X_LIBS -L$x_libraries"
+    # For Solaris; some versions of Sun CC require a space after -R and
+    # others require no space.  Words are not sufficient . . . .
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5
+$as_echo_n "checking whether -R must be followed by a space... " >&6; }
+    ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries"
+    ac_xsave_c_werror_flag=$ac_c_werror_flag
+    ac_c_werror_flag=yes
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       X_LIBS="$X_LIBS -R$x_libraries"
+else
+  LIBS="$ac_xsave_LIBS -R $x_libraries"
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	  X_LIBS="$X_LIBS -R $x_libraries"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither works" >&5
+$as_echo "neither works" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    ac_c_werror_flag=$ac_xsave_c_werror_flag
+    LIBS=$ac_xsave_LIBS
+  fi
+
+  # Check for system-dependent libraries X programs must link with.
+  # Do this before checking for the system-independent R6 libraries
+  # (-lICE), since we may need -lsocket or whatever for X linking.
+
+  if test "$ISC" = yes; then
+    X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet"
+  else
+    # Martyn Johnson says this is needed for Ultrix, if the X
+    # libraries were built with DECnet support.  And Karl Berry says
+    # the Alpha needs dnet_stub (dnet does not exist).
+    ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char XOpenDisplay ();
+int
+main ()
+{
+return XOpenDisplay ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5
+$as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; }
+if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldnet  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dnet_ntoa ();
+int
+main ()
+{
+return dnet_ntoa ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dnet_dnet_ntoa=yes
+else
+  ac_cv_lib_dnet_dnet_ntoa=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5
+$as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; }
+if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then :
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"
+fi
+
+    if test $ac_cv_lib_dnet_dnet_ntoa = no; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5
+$as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; }
+if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldnet_stub  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dnet_ntoa ();
+int
+main ()
+{
+return dnet_ntoa ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dnet_stub_dnet_ntoa=yes
+else
+  ac_cv_lib_dnet_stub_dnet_ntoa=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5
+$as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; }
+if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then :
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"
+fi
+
+    fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LIBS="$ac_xsave_LIBS"
+
+    # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT,
+    # to get the SysV transport functions.
+    # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4)
+    # needs -lnsl.
+    # The nsl library prevents programs from opening the X display
+    # on Irix 5.2, according to T.E. Dickey.
+    # The functions gethostbyname, getservbyname, and inet_addr are
+    # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking.
+    ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
+if test "x$ac_cv_func_gethostbyname" = xyes; then :
+
+fi
+
+    if test $ac_cv_func_gethostbyname = no; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
+$as_echo_n "checking for gethostbyname in -lnsl... " >&6; }
+if ${ac_cv_lib_nsl_gethostbyname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_nsl_gethostbyname=yes
+else
+  ac_cv_lib_nsl_gethostbyname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5
+$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
+if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then :
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl"
+fi
+
+      if test $ac_cv_lib_nsl_gethostbyname = no; then
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5
+$as_echo_n "checking for gethostbyname in -lbsd... " >&6; }
+if ${ac_cv_lib_bsd_gethostbyname+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbsd  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_bsd_gethostbyname=yes
+else
+  ac_cv_lib_bsd_gethostbyname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5
+$as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; }
+if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then :
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd"
+fi
+
+      fi
+    fi
+
+    # lieder@skyler.mavd.honeywell.com says without -lsocket,
+    # socket/setsockopt and other routines are undefined under SCO ODT
+    # 2.0.  But -lsocket is broken on IRIX 5.2 (and is not necessary
+    # on later versions), says Simon Leinen: it contains gethostby*
+    # variants that don't use the name server (or something).  -lsocket
+    # must be given before -lnsl if both are needed.  We assume that
+    # if connect needs -lnsl, so does gethostbyname.
+    ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
+if test "x$ac_cv_func_connect" = xyes; then :
+
+fi
+
+    if test $ac_cv_func_connect = no; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5
+$as_echo_n "checking for connect in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_connect+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char connect ();
+int
+main ()
+{
+return connect ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_socket_connect=yes
+else
+  ac_cv_lib_socket_connect=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5
+$as_echo "$ac_cv_lib_socket_connect" >&6; }
+if test "x$ac_cv_lib_socket_connect" = xyes; then :
+  X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS"
+fi
+
+    fi
+
+    # Guillermo Gomez says -lposix is necessary on A/UX.
+    ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove"
+if test "x$ac_cv_func_remove" = xyes; then :
+
+fi
+
+    if test $ac_cv_func_remove = no; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5
+$as_echo_n "checking for remove in -lposix... " >&6; }
+if ${ac_cv_lib_posix_remove+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lposix  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char remove ();
+int
+main ()
+{
+return remove ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_posix_remove=yes
+else
+  ac_cv_lib_posix_remove=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5
+$as_echo "$ac_cv_lib_posix_remove" >&6; }
+if test "x$ac_cv_lib_posix_remove" = xyes; then :
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix"
+fi
+
+    fi
+
+    # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
+    ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat"
+if test "x$ac_cv_func_shmat" = xyes; then :
+
+fi
+
+    if test $ac_cv_func_shmat = no; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5
+$as_echo_n "checking for shmat in -lipc... " >&6; }
+if ${ac_cv_lib_ipc_shmat+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lipc  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shmat ();
+int
+main ()
+{
+return shmat ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_ipc_shmat=yes
+else
+  ac_cv_lib_ipc_shmat=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5
+$as_echo "$ac_cv_lib_ipc_shmat" >&6; }
+if test "x$ac_cv_lib_ipc_shmat" = xyes; then :
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc"
+fi
+
+    fi
+  fi
+
+  # Check for libraries that X11R6 Xt/Xaw programs need.
+  ac_save_LDFLAGS=$LDFLAGS
+  test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries"
+  # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to
+  # check for ICE first), but we must link in the order -lSM -lICE or
+  # we get undefined symbols.  So assume we have SM if we have ICE.
+  # These have to be linked with before -lX11, unlike the other
+  # libraries we check for below, so use a different variable.
+  # John Interrante, Karl Berry
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5
+$as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; }
+if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lICE $X_EXTRA_LIBS $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char IceConnectionNumber ();
+int
+main ()
+{
+return IceConnectionNumber ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_ICE_IceConnectionNumber=yes
+else
+  ac_cv_lib_ICE_IceConnectionNumber=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5
+$as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; }
+if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then :
+  X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"
+fi
+
+  LDFLAGS=$ac_save_LDFLAGS
+
+fi
+
+if test "$no_x" = "yes"; then
+    echo
+    echo "ERROR: Could not find X Window System headers/libraries."
+    if test -f /etc/debian_version; then
+       echo "Probably you need to install the libx11-dev package."
+    elif test -f /etc/redhat-release; then
+       echo "Probably you need to install the libX11-devel package."
+    fi
+    echo "To specify paths manually, use the options --x-includes and --x-libraries."
+    echo
+    exit 1
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
+$as_echo_n "checking for library containing socket... " >&6; }
+if ${ac_cv_search_socket+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' socket; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_socket=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_socket+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_socket+:} false; then :
+
+else
+  ac_cv_search_socket=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5
+$as_echo "$ac_cv_search_socket" >&6; }
+ac_res=$ac_cv_search_socket
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_aton" >&5
+$as_echo_n "checking for library containing inet_aton... " >&6; }
+if ${ac_cv_search_inet_aton+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inet_aton ();
+int
+main ()
+{
+return inet_aton ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' resolv; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_inet_aton=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_inet_aton+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_inet_aton+:} false; then :
+
+else
+  ac_cv_search_inet_aton=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_aton" >&5
+$as_echo "$ac_cv_search_inet_aton" >&6; }
+ac_res=$ac_cv_search_inet_aton
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_select_h" = xyes; then :
+  $as_echo "#define HAVE_SYS_SELECT_H 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "sys/modem.h" "ac_cv_header_sys_modem_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_modem_h" = xyes; then :
+  $as_echo "#define HAVE_SYS_MODEM_H 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "sys/filio.h" "ac_cv_header_sys_filio_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_filio_h" = xyes; then :
+  $as_echo "#define HAVE_SYS_FILIO_H 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "sys/strtio.h" "ac_cv_header_sys_strtio_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_strtio_h" = xyes; then :
+  $as_echo "#define HAVE_SYS_STRTIO_H 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default"
+if test "x$ac_cv_header_locale_h" = xyes; then :
+  $as_echo "#define HAVE_LOCALE_H 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "langinfo.h" "ac_cv_header_langinfo_h" "$ac_includes_default"
+if test "x$ac_cv_header_langinfo_h" = xyes; then :
+  $as_echo "#define HAVE_LANGINFO_H 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "sysexits.h" "ac_cv_header_sysexits_h" "$ac_includes_default"
+if test "x$ac_cv_header_sysexits_h" = xyes; then :
+  $as_echo "#define HAVE_SYSEXITS_H 1" >>confdefs.h
+
+fi
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+
+
+
+#
+# OpenSSL detection borrowed from stunnel
+#
+checkssldir() { :
+    if test -f "$1/include/openssl/ssl.h"; then
+        ssldir="$1"
+        return 0
+    fi
+    return 1
+}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL directory" >&5
+$as_echo_n "checking for OpenSSL directory... " >&6; }
+
+# Check whether --with-openssl was given.
+if test "${with_openssl+set}" = set; then :
+  withval=$with_openssl;
+                checkssldir "$withval"
+
+else
+
+                for maindir in /usr/local /usr/lib /usr/pkg /usr /var/ssl /opt; do
+            for dir in $maindir $maindir/openssl $maindir/ssl; do
+                checkssldir $dir && break 2
+            done
+        done
+
+
+fi
+
+if test -z "$ssldir"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: Not found" >&5
+$as_echo "Not found" >&6; }
+    echo
+    echo "ERROR: Could not find OpenSSL headers/libraries."
+    if test -f /etc/debian_version; then
+       echo "Probably you need to install the libssl-dev package."
+    elif test -f /etc/redhat-release; then
+       echo "Probably you need to install the openssl-devel package."
+    fi
+    echo "To specify a path manually, use the --with-openssl option."
+    echo
+    exit 1
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssldir" >&5
+$as_echo "$ssldir" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define ssldir "$ssldir"
+_ACEOF
+
+
+CFLAGS="$CFLAGS -I$ssldir/include"
+# Check whether --enable-static-openssl was given.
+if test "${enable_static_openssl+set}" = set; then :
+  enableval=$enable_static_openssl; static_openssl=yes
+else
+  static_openssl=no
+fi
+
+if test x"$static_openssl" = "xyes"; then
+    # OpenSSL generally relies on libz
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing deflate" >&5
+$as_echo_n "checking for library containing deflate... " >&6; }
+if ${ac_cv_search_deflate+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char deflate ();
+int
+main ()
+{
+return deflate ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' z; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_deflate=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_deflate+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_deflate+:} false; then :
+
+else
+  ac_cv_search_deflate=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflate" >&5
+$as_echo "$ac_cv_search_deflate" >&6; }
+ac_res=$ac_cv_search_deflate
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+    LIBS="-L$ssldir/lib -L$ssldir/lib64 -Wl,-Bstatic -lssl -lcrypto -Wl,-Bdynamic $LIBS"
+else
+    LIBS="-L$ssldir/lib -L$ssldir/lib64 -lssl -lcrypto $LIBS"
+
+    #
+    # target-specific stuff
+    #
+    case "$host" in
+    *-*-solaris*)
+        LDFLAGS="$LDFLAGS -R$ssldir/lib"
+        ;;
+    *-dec-osf*)
+        LDFLAGS="$LDFLAGS -Wl,-rpath,$ssldir/lib"
+        ;;
+    esac
+fi
+
+# Check whether --enable-credssp was given.
+if test "${enable_credssp+set}" = set; then :
+  enableval=$enable_credssp;
+fi
+
+# Check whether --enable-static-gssglue was given.
+if test "${enable_static_gssglue+set}" = set; then :
+  enableval=$enable_static_gssglue; static_gssglue=yes
+else
+  static_gssglue=no
+fi
+
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=0.9.0
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		PKG_CONFIG=""
+	fi
+fi
+if test "x$enable_credssp" != "xno"; then :
+
+	  if test -n "$PKG_CONFIG"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GSSGLUE" >&5
+$as_echo_n "checking for GSSGLUE... " >&6; }
+
+if test -n "$GSSGLUE_CFLAGS"; then
+    pkg_cv_GSSGLUE_CFLAGS="$GSSGLUE_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libgssglue\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libgssglue") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GSSGLUE_CFLAGS=`$PKG_CONFIG --cflags "libgssglue" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$GSSGLUE_LIBS"; then
+    pkg_cv_GSSGLUE_LIBS="$GSSGLUE_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libgssglue\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libgssglue") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GSSGLUE_LIBS=`$PKG_CONFIG --libs "libgssglue" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        GSSGLUE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libgssglue" 2>&1`
+        else
+	        GSSGLUE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libgssglue" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$GSSGLUE_PKG_ERRORS" >&5
+
+	WITH_CREDSSP=0
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	WITH_CREDSSP=0
+else
+	GSSGLUE_CFLAGS=$pkg_cv_GSSGLUE_CFLAGS
+	GSSGLUE_LIBS=$pkg_cv_GSSGLUE_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	WITH_CREDSSP=1
+fi
+	  fi
+
+	  if test x"$WITH_CREDSSP" = "x1"; then
+	      CREDSSPOBJ="cssp.o"
+	      CFLAGS="$CFLAGS $GSSGLUE_CFLAGS"
+
+	      if test "x$static_gssglue" != "xno"; then :
+
+	          LIBS="$LIBS -Wl,-Bstatic -lgssglue -Wl,-Bdynamic"
+
+else
+
+	          LIBS="$LIBS -lgssglue"
+
+fi
+
+	      $as_echo "#define WITH_CREDSSP 1" >>confdefs.h
+
+	  else
+		echo
+		echo "CredSSP support requires libgssglue, install the dependency"
+		echo "or disable the feature using --disable-credssp."
+		echo
+		exit 1
+	  fi
+
+fi
+
+
+# xrandr
+if test -n "$PKG_CONFIG"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XRANDR" >&5
+$as_echo_n "checking for XRANDR... " >&6; }
+
+if test -n "$XRANDR_CFLAGS"; then
+    pkg_cv_XRANDR_CFLAGS="$XRANDR_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xrandr\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "xrandr") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_XRANDR_CFLAGS=`$PKG_CONFIG --cflags "xrandr" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$XRANDR_LIBS"; then
+    pkg_cv_XRANDR_LIBS="$XRANDR_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xrandr\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "xrandr") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_XRANDR_LIBS=`$PKG_CONFIG --libs "xrandr" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        XRANDR_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "xrandr" 2>&1`
+        else
+	        XRANDR_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "xrandr" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$XRANDR_PKG_ERRORS" >&5
+
+	HAVE_XRANDR=0
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	HAVE_XRANDR=0
+else
+	XRANDR_CFLAGS=$pkg_cv_XRANDR_CFLAGS
+	XRANDR_LIBS=$pkg_cv_XRANDR_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	HAVE_XRANDR=1
+fi
+fi
+if test x"$HAVE_XRANDR" = "x1"; then
+    CFLAGS="$CFLAGS $XRANDR_CFLAGS"
+    LIBS="$LIBS $XRANDR_LIBS"
+    $as_echo "#define HAVE_XRANDR 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-smartcard was given.
+if test "${enable_smartcard+set}" = set; then :
+  enableval=$enable_smartcard;
+fi
+
+if test "x$enable_smartcard" != "xno"; then :
+
+	case "$OSTYPE" in
+	     darwin*)
+		ac_fn_c_check_header_mongrel "$LINENO" "PCSC/pcsclite.h" "ac_cv_header_PCSC_pcsclite_h" "$ac_includes_default"
+if test "x$ac_cv_header_PCSC_pcsclite_h" = xyes; then :
+  WITH_SCARD=1
+else
+  WITH_SCARD=0
+fi
+
+
+		PCSCLITE_CFLAGS=""
+		PCSCLITE_LIBS="-framework PCSC"
+		;;
+	     *)
+		if test -n "$PKG_CONFIG"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PCSCLITE" >&5
+$as_echo_n "checking for PCSCLITE... " >&6; }
+
+if test -n "$PCSCLITE_CFLAGS"; then
+    pkg_cv_PCSCLITE_CFLAGS="$PCSCLITE_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpcsclite\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libpcsclite") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_PCSCLITE_CFLAGS=`$PKG_CONFIG --cflags "libpcsclite" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$PCSCLITE_LIBS"; then
+    pkg_cv_PCSCLITE_LIBS="$PCSCLITE_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpcsclite\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libpcsclite") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_PCSCLITE_LIBS=`$PKG_CONFIG --libs "libpcsclite" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        PCSCLITE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpcsclite" 2>&1`
+        else
+	        PCSCLITE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpcsclite" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$PCSCLITE_PKG_ERRORS" >&5
+
+	WITH_SCARD=0
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	WITH_SCARD=0
+else
+	PCSCLITE_CFLAGS=$pkg_cv_PCSCLITE_CFLAGS
+	PCSCLITE_LIBS=$pkg_cv_PCSCLITE_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	WITH_SCARD=1
+fi
+		fi
+		;;
+	esac
+
+	if test x"$WITH_SCARD" = "x1"; then
+	   SCARDOBJ="scard.o"
+	   CFLAGS="$CFLAGS $PCSCLITE_CFLAGS"
+	   LIBS="$LIBS $PCSCLITE_LIBS"
+	   $as_echo "#define WITH_SCARD 1" >>confdefs.h
+
+	else
+	   echo
+	   echo "SmartCard support requires PCSC, install the dependency"
+	   echo "or disable the feature using --disable-smartcard."
+	   echo
+	   exit 1
+	fi
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for old version of PCSC" >&5
+$as_echo_n "checking for old version of PCSC... " >&6; }
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+		#include <stdlib.h>
+		#ifdef __APPLE__
+		#include <PCSC/wintypes.h>
+		#include <PCSC/winscard.h>
+		#else
+		#include <winscard.h>
+		#endif
+
+int
+main ()
+{
+SCardControl(NULL, NULL, 0, NULL, NULL);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+$as_echo "#define WITH_PCSC120 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+
+#
+# Alignment
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if architecture needs alignment" >&5
+$as_echo_n "checking if architecture needs alignment... " >&6; }
+if test "$cross_compiling" = yes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: assuming yes" >&5
+$as_echo "assuming yes" >&6; }
+  $as_echo "#define NEED_ALIGN 1" >>confdefs.h
+
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <signal.h>
+int main(int argc, char **argv)
+{
+	unsigned char test[8] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
+	signal(SIGBUS, exit);
+	signal(SIGABRT, exit);
+	signal(SIGSEGV, exit);
+	if (*((unsigned int *)(test + 1)) != 0x55443322 && *((unsigned int *)(test + 1)) != 0x22334455) {
+		return 1;
+	}
+	return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  $as_echo "#define NEED_ALIGN 1" >>confdefs.h
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+
+#
+# EGD
+#
+
+# Check whether --with-egd-socket was given.
+if test "${with_egd_socket+set}" = set; then :
+  withval=$with_egd_socket; EGD_SOCKET="$withval"
+else
+  EGD_SOCKET="/var/run/egd-pool"
+
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define EGD_SOCKET "$EGD_SOCKET"
+_ACEOF
+
+
+
+#
+# rdp2vnc
+#
+vncserverconfig=libvncserver-config
+
+# Check whether --with-libvncserver-config was given.
+if test "${with_libvncserver_config+set}" = set; then :
+  withval=$with_libvncserver_config; vncserverconfig="$withval"
+
+fi
+
+
+# Check whether --with-libvncserver was given.
+if test "${with_libvncserver+set}" = set; then :
+  withval=$with_libvncserver;
+    VNCINC=`$vncserverconfig --cflags`
+
+    LDVNC=`$vncserverconfig --libs`
+
+    VNCLINK=`$vncserverconfig --link`
+
+    RDP2VNCTARGET="rdp2vnc"
+
+
+
+fi
+
+
+#
+# sound
+#
+
+sound="yes"
+
+# Check whether --with-sound was given.
+if test "${with_sound+set}" = set; then :
+  withval=$with_sound;
+    sound="$withval"
+
+fi
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "sys/soundcard.h" "ac_cv_header_sys_soundcard_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_soundcard_h" = xyes; then :
+  HAVE_OSS=1
+else
+  HAVE_OSS=0
+fi
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "dmedia/audio.h" "ac_cv_header_dmedia_audio_h" "$ac_includes_default"
+if test "x$ac_cv_header_dmedia_audio_h" = xyes; then :
+  HAVE_SGI=1
+else
+  HAVE_SGI=0
+fi
+
+
+ac_fn_c_check_header_mongrel "$LINENO" "sys/audioio.h" "ac_cv_header_sys_audioio_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_audioio_h" = xyes; then :
+  HAVE_SUN=1
+else
+  HAVE_SUN=0
+fi
+
+
+
+# Check whether --enable-static-libsamplerate was given.
+if test "${enable_static_libsamplerate+set}" = set; then :
+  enableval=$enable_static_libsamplerate; static_libsamplerate=yes
+else
+  static_libsamplerate=no
+fi
+
+
+if test -n "$PKG_CONFIG"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBAO" >&5
+$as_echo_n "checking for LIBAO... " >&6; }
+
+if test -n "$LIBAO_CFLAGS"; then
+    pkg_cv_LIBAO_CFLAGS="$LIBAO_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ao\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "ao") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBAO_CFLAGS=`$PKG_CONFIG --cflags "ao" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$LIBAO_LIBS"; then
+    pkg_cv_LIBAO_LIBS="$LIBAO_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"ao\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "ao") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBAO_LIBS=`$PKG_CONFIG --libs "ao" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        LIBAO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "ao" 2>&1`
+        else
+	        LIBAO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "ao" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$LIBAO_PKG_ERRORS" >&5
+
+	HAVE_LIBAO=0
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	HAVE_LIBAO=0
+else
+	LIBAO_CFLAGS=$pkg_cv_LIBAO_CFLAGS
+	LIBAO_LIBS=$pkg_cv_LIBAO_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	HAVE_LIBAO=1
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ALSA" >&5
+$as_echo_n "checking for ALSA... " >&6; }
+
+if test -n "$ALSA_CFLAGS"; then
+    pkg_cv_ALSA_CFLAGS="$ALSA_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "alsa") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_ALSA_CFLAGS=`$PKG_CONFIG --cflags "alsa" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$ALSA_LIBS"; then
+    pkg_cv_ALSA_LIBS="$ALSA_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "alsa") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_ALSA_LIBS=`$PKG_CONFIG --libs "alsa" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        ALSA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "alsa" 2>&1`
+        else
+	        ALSA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "alsa" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$ALSA_PKG_ERRORS" >&5
+
+	HAVE_ALSA=0
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	HAVE_ALSA=0
+else
+	ALSA_CFLAGS=$pkg_cv_ALSA_CFLAGS
+	ALSA_LIBS=$pkg_cv_ALSA_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	HAVE_ALSA=1
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBSAMPLERATE" >&5
+$as_echo_n "checking for LIBSAMPLERATE... " >&6; }
+
+if test -n "$LIBSAMPLERATE_CFLAGS"; then
+    pkg_cv_LIBSAMPLERATE_CFLAGS="$LIBSAMPLERATE_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"samplerate\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "samplerate") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBSAMPLERATE_CFLAGS=`$PKG_CONFIG --cflags "samplerate" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$LIBSAMPLERATE_LIBS"; then
+    pkg_cv_LIBSAMPLERATE_LIBS="$LIBSAMPLERATE_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"samplerate\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "samplerate") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBSAMPLERATE_LIBS=`$PKG_CONFIG --libs "samplerate" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        LIBSAMPLERATE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "samplerate" 2>&1`
+        else
+	        LIBSAMPLERATE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "samplerate" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$LIBSAMPLERATE_PKG_ERRORS" >&5
+
+	HAVE_LIBSAMPLERATE=0
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+	HAVE_LIBSAMPLERATE=0
+else
+	LIBSAMPLERATE_CFLAGS=$pkg_cv_LIBSAMPLERATE_CFLAGS
+	LIBSAMPLERATE_LIBS=$pkg_cv_LIBSAMPLERATE_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	HAVE_LIBSAMPLERATE=1
+fi
+    if test x"$HAVE_LIBSAMPLERATE" = "x1"; then
+        $as_echo "#define HAVE_LIBSAMPLERATE 1" >>confdefs.h
+
+        if test x"$static_libsamplerate" = "xyes"; then
+            _libsamplerate_libdir=`$PKG_CONFIG --errors-to-stdout --variable=libdir samplerate`
+            LIBSAMPLERATE_LIBS="$_libsamplerate_libdir""/libsamplerate.a"
+            LIBSAMPLERATE_LIBS="$LIBSAMPLERATE_LIBS -lm"
+        fi
+    fi
+fi
+
+if test "$sound" != "no"; then
+    SOUNDOBJ="$SOUNDOBJ rdpsnd.o rdpsnd_dsp.o"
+    CFLAGS="$CFLAGS $LIBSAMPLERATE_CFLAGS"
+    LIBS="$LIBS $LIBSAMPLERATE_LIBS"
+    $as_echo "#define WITH_RDPSND 1" >>confdefs.h
+
+fi
+
+case $sound in
+    yes)
+        if test x"$HAVE_OSS" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_oss.o"
+            $as_echo "#define RDPSND_OSS 1" >>confdefs.h
+
+        fi
+
+        if test x"$HAVE_SGI" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_sgi.o"
+            LIBS="$LIBS -laudio"
+            $as_echo "#define RDPSND_SGI 1" >>confdefs.h
+
+        fi
+
+        if test x"$HAVE_SUN" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_sun.o"
+            $as_echo "#define RDPSND_SUN 1" >>confdefs.h
+
+        fi
+
+        if test x"$HAVE_ALSA" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_alsa.o"
+            CFLAGS="$CFLAGS $ALSA_CFLAGS"
+            LIBS="$LIBS $ALSA_LIBS"
+            $as_echo "#define RDPSND_ALSA 1" >>confdefs.h
+
+        fi
+
+        if test x"$HAVE_LIBAO" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_libao.o"
+            CFLAGS="$CFLAGS $LIBAO_CFLAGS"
+            LIBS="$LIBS $LIBAO_LIBS"
+            $as_echo "#define RDPSND_LIBAO 1" >>confdefs.h
+
+        fi
+
+        ;;
+
+    oss)
+        if test x"$HAVE_OSS" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_oss.o"
+            $as_echo "#define RDPSND_OSS 1" >>confdefs.h
+
+        else
+            as_fn_error $? "Selected sound system is not available." "$LINENO" 5
+        fi
+        ;;
+
+    sgi)
+        if test x"$HAVE_SGI" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_sgi.o"
+            LIBS="$LIBS -laudio"
+            $as_echo "#define RDPSND_SGI 1" >>confdefs.h
+
+        else
+            as_fn_error $? "Selected sound system is not available." "$LINENO" 5
+        fi
+        ;;
+
+    sun)
+        if test x"$HAVE_SUN" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_sun.o"
+            $as_echo "#define RDPSND_SUN 1" >>confdefs.h
+
+        else
+            as_fn_error $? "Selected sound system is not available." "$LINENO" 5
+        fi
+        ;;
+
+    alsa)
+        if test x"$HAVE_ALSA" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_alsa.o"
+            CFLAGS="$CFLAGS $ALSA_CFLAGS"
+            LIBS="$LIBS $ALSA_LIBS"
+            $as_echo "#define RDPSND_ALSA 1" >>confdefs.h
+
+        else
+            as_fn_error $? "Selected sound system is not available." "$LINENO" 5
+        fi
+        ;;
+
+    libao)
+        if test x"$HAVE_LIBAO" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_libao.o"
+            CFLAGS="$CFLAGS $LIBAO_CFLAGS"
+            LIBS="$LIBS $LIBAO_LIBS"
+            $as_echo "#define RDPSND_LIBAO 1" >>confdefs.h
+
+        else
+            as_fn_error $? "Selected sound system is not available." "$LINENO" 5
+        fi
+        ;;
+
+    no)
+        ;;
+
+    *)
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: sound support disabled" >&5
+$as_echo "$as_me: WARNING: sound support disabled" >&2;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Currently supported systems are Open Sound System (oss), SGI AL (sgi), Sun/BSD (sun), ALSA (alsa) and libao" >&5
+$as_echo "$as_me: WARNING: Currently supported systems are Open Sound System (oss), SGI AL (sgi), Sun/BSD (sun), ALSA (alsa) and libao" >&2;}
+        ;;
+esac
+
+
+
+#
+# dirfd
+#
+
+
+
+
+
+  ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5
+$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; }
+if eval \${$as_ac_Header+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_ac_Header=yes"
+else
+  eval "$as_ac_Header=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$as_ac_Header
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+$as_echo_n "checking for library containing opendir... " >&6; }
+if ${ac_cv_search_opendir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dir; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_opendir+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_opendir+:} false; then :
+
+else
+  ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+$as_echo "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+$as_echo_n "checking for library containing opendir... " >&6; }
+if ${ac_cv_search_opendir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' x; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_opendir+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_opendir+:} false; then :
+
+else
+  ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+$as_echo "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+fi
+
+  dirfd_headers='
+#if HAVE_DIRENT_H
+# include <dirent.h>
+#else /* not HAVE_DIRENT_H */
+# define dirent direct
+# if HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif /* HAVE_SYS_NDIR_H */
+# if HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif /* HAVE_SYS_DIR_H */
+# if HAVE_NDIR_H
+#  include <ndir.h>
+# endif /* HAVE_NDIR_H */
+#endif /* HAVE_DIRENT_H */
+'
+  for ac_func in dirfd
+do :
+  ac_fn_c_check_func "$LINENO" "dirfd" "ac_cv_func_dirfd"
+if test "x$ac_cv_func_dirfd" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DIRFD 1
+_ACEOF
+
+fi
+done
+
+  ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "$dirfd_headers
+"
+if test "x$ac_cv_have_decl_dirfd" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_DIRFD $ac_have_decl
+_ACEOF
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether dirfd is a macro" >&5
+$as_echo_n "checking whether dirfd is a macro... " >&6; }
+if ${jm_cv_func_dirfd_macro+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$dirfd_headers
+#ifdef dirfd
+ dirent_header_defines_dirfd
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "dirent_header_defines_dirfd" >/dev/null 2>&1; then :
+  jm_cv_func_dirfd_macro=yes
+else
+  jm_cv_func_dirfd_macro=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $jm_cv_func_dirfd_macro" >&5
+$as_echo "$jm_cv_func_dirfd_macro" >&6; }
+
+  # Use the replacement only if we have no function, macro,
+  # or declaration with that name.
+  if test $ac_cv_func_dirfd,$ac_cv_have_decl_dirfd,$jm_cv_func_dirfd_macro \
+      = no,no,no; then
+    ac_fn_c_check_func "$LINENO" "dirfd" "ac_cv_func_dirfd"
+if test "x$ac_cv_func_dirfd" = xyes; then :
+  $as_echo "#define HAVE_DIRFD 1" >>confdefs.h
+
+else
+  case " $LIBOBJS " in
+  *" dirfd.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS dirfd.$ac_objext"
+ ;;
+esac
+
+fi
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to get the file descriptor associated with an open DIR*" >&5
+$as_echo_n "checking how to get the file descriptor associated with an open DIR*... " >&6; }
+if ${gl_cv_sys_dir_fd_member_name+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+        dirfd_save_CFLAGS=$CFLAGS
+	for ac_expr in d_fd dd_fd; do
+
+	  CFLAGS="$CFLAGS -DDIR_FD_MEMBER_NAME=$ac_expr"
+	  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$dirfd_headers
+
+int
+main ()
+{
+DIR *dir_p = opendir("."); (void) dir_p->DIR_FD_MEMBER_NAME;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  dir_fd_found=yes
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	  CFLAGS=$dirfd_save_CFLAGS
+	  test "$dir_fd_found" = yes && break
+	done
+	test "$dir_fd_found" = yes || ac_expr=no_such_member
+
+	gl_cv_sys_dir_fd_member_name=$ac_expr
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_sys_dir_fd_member_name" >&5
+$as_echo "$gl_cv_sys_dir_fd_member_name" >&6; }
+    if test $gl_cv_sys_dir_fd_member_name != no_such_member; then
+
+cat >>confdefs.h <<_ACEOF
+#define DIR_FD_MEMBER_NAME $gl_cv_sys_dir_fd_member_name
+_ACEOF
+
+    fi
+
+  fi
+
+
+#
+# iconv
+#
+
+
+
+
+
+
+
+# Check whether --with-libiconv-prefix was given.
+if test "${with_libiconv_prefix+set}" = set; then :
+  withval=$with_libiconv_prefix;
+    for dir in `echo "$withval" | tr : ' '`; do
+      if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi
+      if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi
+    done
+
+fi
+
+  ac_fn_c_check_header_mongrel "$LINENO" "iconv.h" "ac_cv_header_iconv_h" "$ac_includes_default"
+if test "x$ac_cv_header_iconv_h" = xyes; then :
+  $as_echo "#define HAVE_ICONV_H 1" >>confdefs.h
+
+fi
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5
+$as_echo_n "checking for iconv... " >&6; }
+if ${am_cv_func_iconv+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    am_cv_func_iconv="no, consider installing GNU libiconv"
+    am_cv_lib_iconv=no
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+       iconv(cd,NULL,NULL,NULL,NULL);
+       iconv_close(cd);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  am_cv_func_iconv=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    if test "$am_cv_func_iconv" != yes; then
+      am_save_LIBS="$LIBS"
+      LIBS="$LIBS -liconv"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+         iconv(cd,NULL,NULL,NULL,NULL);
+         iconv_close(cd);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  am_cv_lib_iconv=yes
+        am_cv_func_iconv=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+      LIBS="$am_save_LIBS"
+    fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5
+$as_echo "$am_cv_func_iconv" >&6; }
+  if test "$am_cv_func_iconv" = yes; then
+
+$as_echo "#define HAVE_ICONV 1" >>confdefs.h
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv declaration" >&5
+$as_echo_n "checking for iconv declaration... " >&6; }
+    if ${am_cv_proto_iconv+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  am_cv_proto_iconv_arg1=""
+else
+  am_cv_proto_iconv_arg1="const"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+      am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"
+fi
+
+    am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_t:-
+         }$am_cv_proto_iconv" >&5
+$as_echo "${ac_t:-
+         }$am_cv_proto_iconv" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define ICONV_CONST $am_cv_proto_iconv_arg1
+_ACEOF
+
+  fi
+  LIBICONV=
+  if test "$am_cv_lib_iconv" = yes; then
+    LIBICONV="-liconv"
+  fi
+
+
+LIBS="$LIBS $LIBICONV"
+
+#
+# socklen_t
+# from curl
+
+
+
+
+   ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include <sys/types.h>
+#include <sys/socket.h>
+"
+if test "x$ac_cv_type_socklen_t" = xyes; then :
+
+else
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t equivalent" >&5
+$as_echo_n "checking for socklen_t equivalent... " >&6; }
+      if ${socklen_t_cv_equiv+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+         # Systems have either "struct sockaddr *" or
+         # "void *" as the second argument to getpeername
+         socklen_t_cv_equiv=
+         for arg2 in "struct sockaddr" void; do
+            for t in int size_t unsigned long "unsigned long"; do
+               cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+                  #include <sys/types.h>
+                  #include <sys/socket.h>
+
+                  int getpeername (int, $arg2 *, $t *);
+
+int
+main ()
+{
+
+                  $t len;
+                  getpeername(0,0,&len);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+                  socklen_t_cv_equiv="$t"
+                  break
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+            done
+         done
+
+         if test "x$socklen_t_cv_equiv" = x; then
+            as_fn_error $? "Cannot find a type to use in place of socklen_t" "$LINENO" 5
+         fi
+
+fi
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: $socklen_t_cv_equiv" >&5
+$as_echo "$socklen_t_cv_equiv" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define socklen_t $socklen_t_cv_equiv
+_ACEOF
+
+fi
+
+
+
+#
+# statfs stuff
+#
+for ac_header in sys/vfs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/vfs.h" "ac_cv_header_sys_vfs_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_vfs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_VFS_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in sys/statvfs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/statvfs.h" "ac_cv_header_sys_statvfs_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_statvfs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_STATVFS_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in sys/statfs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/statfs.h" "ac_cv_header_sys_statfs_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_statfs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_STATFS_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in sys/param.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_param_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_PARAM_H 1
+_ACEOF
+
+fi
+
+done
+
+
+mount_includes="\
+  $ac_includes_default
+  #if HAVE_SYS_PARAM_H
+  # include <sys/param.h>
+  #endif
+  "
+
+for ac_header in sys/mount.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "sys/mount.h" "ac_cv_header_sys_mount_h" "$mount_includes
+"
+if test "x$ac_cv_header_sys_mount_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_MOUNT_H 1
+_ACEOF
+
+fi
+
+done
+
+
+#################################################
+# these tests are taken from the GNU fileutils package
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to get filesystem space usage..." >&5
+$as_echo "$as_me: checking how to get filesystem space usage..." >&6;}
+space=no
+
+# Test for statvfs64.
+if test $space = no; then
+  # SVR4
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking statvfs64 function (SVR4)" >&5
+$as_echo_n "checking statvfs64 function (SVR4)... " >&6; }
+if ${fu_cv_sys_stat_statvfs64+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  fu_cv_sys_stat_statvfs64=cross
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/statvfs.h>
+  main ()
+  {
+    struct statvfs64 fsd;
+    exit (statvfs64 (".", &fsd));
+  }
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  fu_cv_sys_stat_statvfs64=yes
+else
+  fu_cv_sys_stat_statvfs64=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $fu_cv_sys_stat_statvfs64" >&5
+$as_echo "$fu_cv_sys_stat_statvfs64" >&6; }
+  if test $fu_cv_sys_stat_statvfs64 = yes; then
+    space=yes
+
+$as_echo "#define STAT_STATVFS64 1" >>confdefs.h
+
+  fi
+fi
+
+# Perform only the link test since it seems there are no variants of the
+# statvfs function.  This check is more than just AC_CHECK_FUNCS(statvfs)
+# because that got a false positive on SCO OSR5.  Adding the declaration
+# of a `struct statvfs' causes this test to fail (as it should) on such
+# systems.  That system is reported to work fine with STAT_STATFS4 which
+# is what it gets when this test fails.
+if test $space = no; then
+  # SVR4
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking statvfs function (SVR4)" >&5
+$as_echo_n "checking statvfs function (SVR4)... " >&6; }
+if ${fu_cv_sys_stat_statvfs+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/statvfs.h>
+int
+main ()
+{
+struct statvfs fsd; statvfs (0, &fsd);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  fu_cv_sys_stat_statvfs=yes
+else
+  fu_cv_sys_stat_statvfs=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $fu_cv_sys_stat_statvfs" >&5
+$as_echo "$fu_cv_sys_stat_statvfs" >&6; }
+  if test $fu_cv_sys_stat_statvfs = yes; then
+    space=yes
+
+$as_echo "#define STAT_STATVFS 1" >>confdefs.h
+
+  fi
+fi
+
+if test $space = no; then
+  # DEC Alpha running OSF/1
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 3-argument statfs function (DEC OSF/1)" >&5
+$as_echo_n "checking for 3-argument statfs function (DEC OSF/1)... " >&6; }
+  if ${fu_cv_sys_stat_statfs3_osf1+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  fu_cv_sys_stat_statfs3_osf1=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+  main ()
+  {
+    struct statfs fsd;
+    fsd.f_fsize = 0;
+    exit (statfs (".", &fsd, sizeof (struct statfs)));
+  }
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  fu_cv_sys_stat_statfs3_osf1=yes
+else
+  fu_cv_sys_stat_statfs3_osf1=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+
+
+#C_MSG_RESULT($fu_cv_sys_stat_statfs3_osf1)
+  if test $fu_cv_sys_stat_statfs3_osf1 = yes; then
+    space=yes
+
+$as_echo "#define STAT_STATFS3_OSF1 1" >>confdefs.h
+
+  fi
+fi
+
+if test $space = no; then
+# AIX
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for two-argument statfs with statfs.bsize member (AIX, 4.3BSD)" >&5
+$as_echo_n "checking for two-argument statfs with statfs.bsize member (AIX, 4.3BSD)... " >&6; }
+  if ${fu_cv_sys_stat_statfs2_bsize+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  fu_cv_sys_stat_statfs2_bsize=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+  main ()
+  {
+  struct statfs fsd;
+  fsd.f_bsize = 0;
+  exit (statfs (".", &fsd));
+  }
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  fu_cv_sys_stat_statfs2_bsize=yes
+else
+  fu_cv_sys_stat_statfs2_bsize=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fu_cv_sys_stat_statfs2_bsize" >&5
+$as_echo "$fu_cv_sys_stat_statfs2_bsize" >&6; }
+  if test $fu_cv_sys_stat_statfs2_bsize = yes; then
+    space=yes
+
+$as_echo "#define STAT_STATFS2_BSIZE 1" >>confdefs.h
+
+  fi
+fi
+
+if test $space = no; then
+# SVR3
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for four-argument statfs (AIX-3.2.5, SVR3)" >&5
+$as_echo_n "checking for four-argument statfs (AIX-3.2.5, SVR3)... " >&6; }
+  if ${fu_cv_sys_stat_statfs4+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  fu_cv_sys_stat_statfs4=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/statfs.h>
+  main ()
+  {
+  struct statfs fsd;
+  exit (statfs (".", &fsd, sizeof fsd, 0));
+  }
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  fu_cv_sys_stat_statfs4=yes
+else
+  fu_cv_sys_stat_statfs4=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fu_cv_sys_stat_statfs4" >&5
+$as_echo "$fu_cv_sys_stat_statfs4" >&6; }
+  if test $fu_cv_sys_stat_statfs4 = yes; then
+    space=yes
+
+$as_echo "#define STAT_STATFS4 1" >>confdefs.h
+
+  fi
+fi
+
+if test $space = no; then
+# 4.4BSD and NetBSD
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for two-argument statfs with statfs.fsize member (4.4BSD and NetBSD)" >&5
+$as_echo_n "checking for two-argument statfs with statfs.fsize member (4.4BSD and NetBSD)... " >&6; }
+  if ${fu_cv_sys_stat_statfs2_fsize+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  fu_cv_sys_stat_statfs2_fsize=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+  main ()
+  {
+  struct statfs fsd;
+  fsd.f_fsize = 0;
+  exit (statfs (".", &fsd));
+  }
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  fu_cv_sys_stat_statfs2_fsize=yes
+else
+  fu_cv_sys_stat_statfs2_fsize=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fu_cv_sys_stat_statfs2_fsize" >&5
+$as_echo "$fu_cv_sys_stat_statfs2_fsize" >&6; }
+  if test $fu_cv_sys_stat_statfs2_fsize = yes; then
+    space=yes
+
+$as_echo "#define STAT_STATFS2_FSIZE 1" >>confdefs.h
+
+  fi
+fi
+
+if test $space = no; then
+  # Ultrix
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for two-argument statfs with struct fs_data (Ultrix)" >&5
+$as_echo_n "checking for two-argument statfs with struct fs_data (Ultrix)... " >&6; }
+  if ${fu_cv_sys_stat_fs_data+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  fu_cv_sys_stat_fs_data=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+#ifdef HAVE_SYS_FS_TYPES_H
+#include <sys/fs_types.h>
+#endif
+  main ()
+  {
+  struct fs_data fsd;
+  /* Ultrix's statfs returns 1 for success,
+     0 for not mounted, -1 for failure.  */
+  exit (statfs (".", &fsd) != 1);
+  }
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  fu_cv_sys_stat_fs_data=yes
+else
+  fu_cv_sys_stat_fs_data=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $fu_cv_sys_stat_fs_data" >&5
+$as_echo "$fu_cv_sys_stat_fs_data" >&6; }
+  if test $fu_cv_sys_stat_fs_data = yes; then
+    space=yes
+
+$as_echo "#define STAT_STATFS2_FS_DATA 1" >>confdefs.h
+
+  fi
+fi
+
+  statxfs_includes="\
+$ac_includes_default
+#if HAVE_SYS_STATVFS_H
+# include <sys/statvfs.h>
+#endif
+#if HAVE_SYS_VFS_H
+# include <sys/vfs.h>
+#endif
+#if !HAVE_SYS_STATVFS_H && !HAVE_SYS_VFS_H
+# if HAVE_SYS_MOUNT_H && HAVE_SYS_PARAM_H
+/* NetBSD 1.5.2 needs these, for the declaration of struct statfs. */
+#  include <sys/param.h>
+#  include <sys/mount.h>
+# elif HAVE_NETINET_IN_H && HAVE_NFS_NFS_CLNT_H && HAVE_NFS_VFS_H
+/* Ultrix 4.4 needs these for the declaration of struct statfs.  */
+#  include <netinet/in.h>
+#  include <nfs/nfs_clnt.h>
+#  include <nfs/vfs.h>
+# endif
+#endif
+"
+
+ac_fn_c_check_member "$LINENO" "struct statfs" "f_namemax" "ac_cv_member_struct_statfs_f_namemax" "$statxfs_includes
+"
+if test "x$ac_cv_member_struct_statfs_f_namemax" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STATFS_F_NAMEMAX 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct statvfs" "f_namemax" "ac_cv_member_struct_statvfs_f_namemax" "$statxfs_includes
+"
+if test "x$ac_cv_member_struct_statvfs_f_namemax" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STATVFS_F_NAMEMAX 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct statfs" "f_namelen" "ac_cv_member_struct_statfs_f_namelen" "$statxfs_includes
+"
+if test "x$ac_cv_member_struct_statfs_f_namelen" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STATFS_F_NAMELEN 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct statvfs" "f_namelen" "ac_cv_member_struct_statvfs_f_namelen" "$statxfs_includes
+"
+if test "x$ac_cv_member_struct_statvfs_f_namelen" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STATVFS_F_NAMELEN 1
+_ACEOF
+
+
+fi
+
+
+#
+# Large file support
+#
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+  enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+	 # IRIX 6.2 and later do not support large files by default,
+	 # so use the C compiler's -n32 option if that helps.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+	 if ac_fn_c_try_compile "$LINENO"; then :
+  break
+fi
+rm -f core conftest.err conftest.$ac_objext
+	 CC="$CC -n32"
+	 if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+	 break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if ${ac_cv_sys_file_offset_bits+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_file_offset_bits=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  if test $ac_cv_sys_file_offset_bits = unknown; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if ${ac_cv_sys_large_files+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+		       && LARGE_OFF_T % 2147483647 == 1)
+		      ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_large_files=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  fi
+
+
+fi
+
+
+#
+# mntent
+#
+ac_fn_c_check_header_mongrel "$LINENO" "mntent.h" "ac_cv_header_mntent_h" "$ac_includes_default"
+if test "x$ac_cv_header_mntent_h" = xyes; then :
+  $as_echo "#define HAVE_MNTENT_H 1" >>confdefs.h
+
+fi
+
+
+for ac_func in setmntent
+do :
+  ac_fn_c_check_func "$LINENO" "setmntent" "ac_cv_func_setmntent"
+if test "x$ac_cv_func_setmntent" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SETMNTENT 1
+_ACEOF
+
+fi
+done
+
+
+#
+# IPv6
+#
+
+# Check whether --with-ipv6 was given.
+if test "${with_ipv6+set}" = set; then :
+  withval=$with_ipv6;
+        if test $withval != "no";
+        then
+	    $as_echo "#define IPv6 1" >>confdefs.h
+
+	fi
+
+fi
+
+
+
+#
+# debugging
+#
+
+# Check whether --with-debug was given.
+if test "${with_debug+set}" = set; then :
+  withval=$with_debug;
+        if test $withval != "no";
+        then
+            $as_echo "#define WITH_DEBUG 1" >>confdefs.h
+
+	fi
+
+fi
+
+
+
+# Check whether --with-debug-kbd was given.
+if test "${with_debug_kbd+set}" = set; then :
+  withval=$with_debug_kbd;
+        if test $withval != "no";
+        then
+            $as_echo "#define WITH_DEBUG_KBD 1" >>confdefs.h
+
+	fi
+
+fi
+
+
+
+# Check whether --with-debug-rdp5 was given.
+if test "${with_debug_rdp5+set}" = set; then :
+  withval=$with_debug_rdp5;
+        if test $withval != "no";
+        then
+            $as_echo "#define WITH_DEBUG_RDP5 1" >>confdefs.h
+
+	fi
+
+fi
+
+
+
+# Check whether --with-debug-clipboard was given.
+if test "${with_debug_clipboard+set}" = set; then :
+  withval=$with_debug_clipboard;
+        if test $withval != "no";
+        then
+            $as_echo "#define WITH_DEBUG_CLIPBOARD 1" >>confdefs.h
+
+	fi
+
+fi
+
+
+
+# Check whether --with-debug-sound was given.
+if test "${with_debug_sound+set}" = set; then :
+  withval=$with_debug_sound;
+        if test $withval != "no";
+        then
+            $as_echo "#define WITH_DEBUG_SOUND 1" >>confdefs.h
+
+	fi
+
+fi
+
+
+
+# Check whether --with-debug-channel was given.
+if test "${with_debug_channel+set}" = set; then :
+  withval=$with_debug_channel;
+        if test $withval != "no";
+        then
+            $as_echo "#define WITH_DEBUG_CHANNEL 1" >>confdefs.h
+
+	fi
+
+fi
+
+
+
+# Check whether --with-debug-seamless was given.
+if test "${with_debug_seamless+set}" = set; then :
+  withval=$with_debug_seamless;
+        if test $withval != "no";
+        then
+            $as_echo "#define WITH_DEBUG_SEAMLESS 1" >>confdefs.h
+
+	fi
+
+fi
+
+
+
+# Check whether --with-debug-smartcard was given.
+if test "${with_debug_smartcard+set}" = set; then :
+  withval=$with_debug_smartcard;
+        if test $withval != "no";
+        then
+		if test x"$WITH_SCARD" = "x1"; then
+			$as_echo "#define WITH_DEBUG_SCARD 1" >>confdefs.h
+
+		fi
+	fi
+
+fi
+
+
+
+# Check whether --with-debug-credssp was given.
+if test "${with_debug_credssp+set}" = set; then :
+  withval=$with_debug_credssp;
+	if test $withval != "no";
+	then
+		if test x"$WITH_CREDSSP" = "x1"; then
+		   $as_echo "#define WITH_DEBUG_CREDSSP 1" >>confdefs.h
+
+		fi
+	fi
+
+fi
+
+
+#
+# target-specific stuff
+#
+case "$host" in
+*-*-hpux*)
+    CFLAGS="$CFLAGS -D_XOPEN_SOURCE_EXTENDED"
+    ;;
+*-*-irix6.5*)
+    LIBS="-L$ssldir/lib32 $LIBS"
+    CFLAGS="$CFLAGS -D__SGI_IRIX__"
+    ;;
+esac
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+	g
+	s/^\n//
+	s/\n/ /g
+	p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by rdesktop $as_me 1.8.3, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+rdesktop config.status 1.8.3
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h |  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X "  :F $CONFIG_FILES      "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
Index: /trunk/src/VBox/RDP/client-1.8.3/configure.ac
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/configure.ac	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/configure.ac	(revision 55121)
@@ -0,0 +1,972 @@
+AC_INIT(rdesktop, 1.8.3)
+
+AC_CONFIG_SRCDIR([rdesktop.c])
+
+AC_CANONICAL_HOST
+
+AC_PROG_CC
+if test "$GCC" = yes; then
+    CFLAGS="$CFLAGS -Wall"
+fi
+
+AC_PROG_INSTALL
+AC_LANG_C
+AC_HEADER_STDC
+AC_C_BIGENDIAN([AC_DEFINE(B_ENDIAN)], [AC_DEFINE(L_ENDIAN)])
+AC_PATH_XTRA
+if test "$no_x" = "yes"; then
+    echo
+    echo "ERROR: Could not find X Window System headers/libraries."
+    if test -f /etc/debian_version; then
+       echo "Probably you need to install the libx11-dev package."
+    elif test -f /etc/redhat-release; then
+       echo "Probably you need to install the libX11-devel package."
+    fi
+    echo "To specify paths manually, use the options --x-includes and --x-libraries."
+    echo
+    exit 1
+fi
+    
+AC_PATH_TOOL(PKG_CONFIG, pkg-config)
+
+AC_SEARCH_LIBS(socket, socket)
+AC_SEARCH_LIBS(inet_aton, resolv)
+
+AC_CHECK_HEADER(sys/select.h, AC_DEFINE(HAVE_SYS_SELECT_H))
+AC_CHECK_HEADER(sys/modem.h, AC_DEFINE(HAVE_SYS_MODEM_H))
+AC_CHECK_HEADER(sys/filio.h, AC_DEFINE(HAVE_SYS_FILIO_H))
+AC_CHECK_HEADER(sys/strtio.h, AC_DEFINE(HAVE_SYS_STRTIO_H))
+AC_CHECK_HEADER(locale.h, AC_DEFINE(HAVE_LOCALE_H))
+AC_CHECK_HEADER(langinfo.h, AC_DEFINE(HAVE_LANGINFO_H))
+AC_CHECK_HEADER(sysexits.h, AC_DEFINE(HAVE_SYSEXITS_H))
+
+AC_CHECK_TOOL(STRIP, strip, :)
+
+dnl Don't depend on pkg-config
+m4_ifdef([PKG_CHECK_MODULES], [], [
+		m4_errprint([warning: pkg-config checks are not available])
+		m4_defun([PKG_CHECK_MODULES], [
+			AC_MSG_WARN([pkg-config not available, cannot check for $2])
+			$4
+		])
+])
+
+#
+# OpenSSL detection borrowed from stunnel
+#
+checkssldir() { :
+    if test -f "$1/include/openssl/ssl.h"; then
+        ssldir="$1"
+        return 0
+    fi
+    return 1
+}
+AC_MSG_CHECKING([for OpenSSL directory])
+AC_ARG_WITH(openssl,
+    [  --with-openssl=DIR          look for OpenSSL at DIR/include, DIR/lib],
+    [
+        dnl Check the specified location only
+        checkssldir "$withval"
+    ],
+    [
+        dnl Search default locations of OpenSSL library
+        for maindir in /usr/local /usr/lib /usr/pkg /usr /var/ssl /opt; do
+            for dir in $maindir $maindir/openssl $maindir/ssl; do
+                checkssldir $dir && break 2
+            done
+        done
+    ]
+)
+if test -z "$ssldir"; then
+    AC_MSG_RESULT([Not found])
+    echo
+    echo "ERROR: Could not find OpenSSL headers/libraries."
+    if test -f /etc/debian_version; then
+       echo "Probably you need to install the libssl-dev package."
+    elif test -f /etc/redhat-release; then
+       echo "Probably you need to install the openssl-devel package."
+    fi
+    echo "To specify a path manually, use the --with-openssl option."
+    echo
+    exit 1
+fi
+AC_MSG_RESULT([$ssldir])
+AC_SUBST(ssldir)
+AC_DEFINE_UNQUOTED(ssldir, "$ssldir")
+
+dnl Add OpenSSL includes and libraries
+CFLAGS="$CFLAGS -I$ssldir/include"
+AC_ARG_ENABLE(static-openssl, 
+             [  --enable-static-openssl link OpenSSL statically],
+             [static_openssl=yes], 
+             [static_openssl=no])
+if test x"$static_openssl" = "xyes"; then
+    # OpenSSL generally relies on libz
+    AC_SEARCH_LIBS(deflate, z)
+    LIBS="-L$ssldir/lib -L$ssldir/lib64 -Wl,-Bstatic -lssl -lcrypto -Wl,-Bdynamic $LIBS"
+else
+    LIBS="-L$ssldir/lib -L$ssldir/lib64 -lssl -lcrypto $LIBS"
+
+    #
+    # target-specific stuff
+    #
+    case "$host" in
+    *-*-solaris*)
+        LDFLAGS="$LDFLAGS -R$ssldir/lib"
+        ;;
+    *-dec-osf*)
+        LDFLAGS="$LDFLAGS -Wl,-rpath,$ssldir/lib"
+        ;;
+    esac
+fi
+
+dnl CredSSP feature
+AC_ARG_ENABLE([credssp], AS_HELP_STRING([--disable-credssp], [disable support for CredSSP]))
+AC_ARG_ENABLE([static-gssglue], AS_HELP_STRING([--enable-static-gssglue]), 
+	      [static_gssglue=yes], [static_gssglue=no])
+AS_IF([test "x$enable_credssp" != "xno"], [
+	  if test -n "$PKG_CONFIG"; then
+	    PKG_CHECK_MODULES(GSSGLUE, libgssglue, [WITH_CREDSSP=1], [WITH_CREDSSP=0])
+	  fi
+
+	  if test x"$WITH_CREDSSP" = "x1"; then
+	      CREDSSPOBJ="cssp.o"
+	      CFLAGS="$CFLAGS $GSSGLUE_CFLAGS"
+
+	      AS_IF([test "x$static_gssglue" != "xno"], [
+	          LIBS="$LIBS -Wl,-Bstatic -lgssglue -Wl,-Bdynamic"
+	      ], [
+	          LIBS="$LIBS -lgssglue"
+	      ])
+
+	      AC_DEFINE(WITH_CREDSSP)
+	  else
+		echo
+		echo "CredSSP support requires libgssglue, install the dependency"
+		echo "or disable the feature using --disable-credssp."
+		echo
+		exit 1
+	  fi
+])
+AC_SUBST(CREDSSPOBJ)
+
+# xrandr
+if test -n "$PKG_CONFIG"; then
+    PKG_CHECK_MODULES(XRANDR, xrandr, [HAVE_XRANDR=1], [HAVE_XRANDR=0])
+fi
+if test x"$HAVE_XRANDR" = "x1"; then
+    CFLAGS="$CFLAGS $XRANDR_CFLAGS"
+    LIBS="$LIBS $XRANDR_LIBS"
+    AC_DEFINE(HAVE_XRANDR)
+fi
+
+dnl Smartcard support
+AC_ARG_ENABLE(smartcard, AS_HELP_STRING([--disable-smartcard], [disable support for smartcard]))
+AS_IF([test "x$enable_smartcard" != "xno"], [
+	case "$OSTYPE" in
+	     darwin*)
+		AC_CHECK_HEADER(PCSC/pcsclite.h, [WITH_SCARD=1], [WITH_SCARD=0])
+		PCSCLITE_CFLAGS=""
+		PCSCLITE_LIBS="-framework PCSC"
+		;;
+	     *)
+		if test -n "$PKG_CONFIG"; then
+		   PKG_CHECK_MODULES(PCSCLITE, libpcsclite, [WITH_SCARD=1], [WITH_SCARD=0])
+		fi
+		;;
+	esac
+
+	if test x"$WITH_SCARD" = "x1"; then
+	   SCARDOBJ="scard.o"
+	   CFLAGS="$CFLAGS $PCSCLITE_CFLAGS"
+	   LIBS="$LIBS $PCSCLITE_LIBS"
+	   AC_DEFINE(WITH_SCARD)
+	else
+	   echo
+	   echo "SmartCard support requires PCSC, install the dependency"
+	   echo "or disable the feature using --disable-smartcard."
+	   echo
+	   exit 1
+	fi
+
+	AC_MSG_CHECKING([for old version of PCSC])
+	AC_TRY_LINK([
+		#include <stdlib.h>
+		#ifdef __APPLE__
+		#include <PCSC/wintypes.h>
+		#include <PCSC/winscard.h>
+		#else
+		#include <winscard.h>
+		#endif
+		],
+		[SCardControl(NULL, NULL, 0, NULL, NULL);],
+		[AC_MSG_RESULT(yes) AC_DEFINE(WITH_PCSC120, 1, [old version of PCSC])],
+		[AC_MSG_RESULT(no)])
+])
+AC_SUBST(SCARDOBJ)
+
+#
+# Alignment
+#
+AC_MSG_CHECKING([if architecture needs alignment])
+AC_TRY_RUN([
+#include <stdlib.h>
+#include <signal.h>
+int main(int argc, char **argv)
+{
+	unsigned char test[8] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
+	signal(SIGBUS, exit);
+	signal(SIGABRT, exit);
+	signal(SIGSEGV, exit);
+	if (*((unsigned int *)(test + 1)) != 0x55443322 && *((unsigned int *)(test + 1)) != 0x22334455) {
+		return 1;
+	}
+	return 0;
+}], 
+ [AC_MSG_RESULT(no)], 
+ [AC_MSG_RESULT(yes) 
+  AC_DEFINE(NEED_ALIGN)], 
+ [AC_MSG_RESULT(assuming yes) 
+  AC_DEFINE(NEED_ALIGN)])
+
+
+#
+# EGD
+#
+AC_ARG_WITH(egd-socket,
+    [  --with-egd-socket=PATH  look for Entropy Gathering Daemon socket at PATH],
+    [EGD_SOCKET="$withval"],
+    [EGD_SOCKET="/var/run/egd-pool"]
+)
+AC_DEFINE_UNQUOTED(EGD_SOCKET, "$EGD_SOCKET")
+
+
+#
+# rdp2vnc
+#
+vncserverconfig=libvncserver-config
+AC_ARG_WITH(libvncserver-config,
+    [  --with-libvncserver-config=CMD  use CMD as libvncserver-config],
+    [vncserverconfig="$withval"]
+)
+AC_ARG_WITH(libvncserver,
+    [  --with-libvncserver     make rdp2vnc],
+    [ 
+    VNCINC=`$vncserverconfig --cflags`
+    AC_SUBST(VNCINC)
+    LDVNC=`$vncserverconfig --libs`
+    AC_SUBST(LDVNC)
+    VNCLINK=`$vncserverconfig --link`
+    AC_SUBST(VNCLINK)
+    RDP2VNCTARGET="rdp2vnc"
+    AC_SUBST(RDP2VNCTARGET)
+    ]
+)
+
+#
+# sound
+#
+
+sound="yes"
+AC_ARG_WITH(sound,
+    [  --with-sound            select sound system ("oss", "sgi", "sun", "alsa" or "libao") ],
+    [ 
+    sound="$withval" 
+    ])
+
+AC_CHECK_HEADER(sys/soundcard.h, [HAVE_OSS=1], [HAVE_OSS=0])
+AC_CHECK_HEADER(dmedia/audio.h, [HAVE_SGI=1], [HAVE_SGI=0])
+AC_CHECK_HEADER(sys/audioio.h, [HAVE_SUN=1], [HAVE_SUN=0])
+
+AC_ARG_ENABLE(static-libsamplerate, 
+    [  --enable-static-libsamplerate link libsamplerate statically], 
+    [static_libsamplerate=yes], 
+    [static_libsamplerate=no])
+
+if test -n "$PKG_CONFIG"; then
+    PKG_CHECK_MODULES(LIBAO, ao, [HAVE_LIBAO=1], [HAVE_LIBAO=0])
+    PKG_CHECK_MODULES(ALSA, alsa, [HAVE_ALSA=1], [HAVE_ALSA=0])
+    PKG_CHECK_MODULES(LIBSAMPLERATE, samplerate, [HAVE_LIBSAMPLERATE=1], [HAVE_LIBSAMPLERATE=0])
+    if test x"$HAVE_LIBSAMPLERATE" = "x1"; then
+        AC_DEFINE(HAVE_LIBSAMPLERATE)
+        if test x"$static_libsamplerate" = "xyes"; then
+            _libsamplerate_libdir=`$PKG_CONFIG --errors-to-stdout --variable=libdir samplerate`
+            LIBSAMPLERATE_LIBS="$_libsamplerate_libdir""/libsamplerate.a"
+            LIBSAMPLERATE_LIBS="$LIBSAMPLERATE_LIBS -lm"
+        fi
+    fi
+fi
+
+if test "$sound" != "no"; then
+    SOUNDOBJ="$SOUNDOBJ rdpsnd.o rdpsnd_dsp.o"
+    CFLAGS="$CFLAGS $LIBSAMPLERATE_CFLAGS"
+    LIBS="$LIBS $LIBSAMPLERATE_LIBS"
+    AC_DEFINE(WITH_RDPSND)
+fi
+
+case $sound in
+    yes)
+        if test x"$HAVE_OSS" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_oss.o"
+            AC_DEFINE(RDPSND_OSS)
+        fi
+
+        if test x"$HAVE_SGI" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_sgi.o"
+            LIBS="$LIBS -laudio"
+            AC_DEFINE(RDPSND_SGI)
+        fi
+
+        if test x"$HAVE_SUN" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_sun.o"
+            AC_DEFINE(RDPSND_SUN)
+        fi
+
+        if test x"$HAVE_ALSA" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_alsa.o"
+            CFLAGS="$CFLAGS $ALSA_CFLAGS"
+            LIBS="$LIBS $ALSA_LIBS"
+            AC_DEFINE(RDPSND_ALSA)
+        fi
+
+        if test x"$HAVE_LIBAO" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_libao.o"
+            CFLAGS="$CFLAGS $LIBAO_CFLAGS"
+            LIBS="$LIBS $LIBAO_LIBS"
+            AC_DEFINE(RDPSND_LIBAO)
+        fi
+
+        ;;
+
+    oss)
+        if test x"$HAVE_OSS" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_oss.o"
+            AC_DEFINE(RDPSND_OSS)
+        else
+            AC_MSG_ERROR([Selected sound system is not available.])
+        fi
+        ;;
+
+    sgi)
+        if test x"$HAVE_SGI" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_sgi.o"
+            LIBS="$LIBS -laudio"
+            AC_DEFINE(RDPSND_SGI)
+        else
+            AC_MSG_ERROR([Selected sound system is not available.])
+        fi
+        ;;
+
+    sun)
+        if test x"$HAVE_SUN" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_sun.o"
+            AC_DEFINE(RDPSND_SUN)
+        else
+            AC_MSG_ERROR([Selected sound system is not available.])
+        fi
+        ;;
+
+    alsa)
+        if test x"$HAVE_ALSA" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_alsa.o"
+            CFLAGS="$CFLAGS $ALSA_CFLAGS"
+            LIBS="$LIBS $ALSA_LIBS"
+            AC_DEFINE(RDPSND_ALSA)
+        else
+            AC_MSG_ERROR([Selected sound system is not available.])
+        fi
+        ;;
+
+    libao)
+        if test x"$HAVE_LIBAO" = "x1"; then
+            SOUNDOBJ="$SOUNDOBJ rdpsnd_libao.o"
+            CFLAGS="$CFLAGS $LIBAO_CFLAGS"
+            LIBS="$LIBS $LIBAO_LIBS"
+            AC_DEFINE(RDPSND_LIBAO)
+        else
+            AC_MSG_ERROR([Selected sound system is not available.])
+        fi
+        ;;
+
+    no)
+        ;;
+
+    *)
+        AC_MSG_WARN([sound support disabled])
+        AC_MSG_WARN([Currently supported systems are Open Sound System (oss), SGI AL (sgi), Sun/BSD (sun), ALSA (alsa) and libao])
+        ;;
+esac
+
+AC_SUBST(SOUNDOBJ)
+
+#
+# dirfd
+#
+dnl Find out how to get the file descriptor associated with an open DIR*.
+dnl From Jim Meyering
+
+AC_DEFUN([UTILS_FUNC_DIRFD],
+[
+
+  AC_HEADER_DIRENT
+  dirfd_headers='
+#if HAVE_DIRENT_H
+# include <dirent.h>
+#else /* not HAVE_DIRENT_H */
+# define dirent direct
+# if HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif /* HAVE_SYS_NDIR_H */
+# if HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif /* HAVE_SYS_DIR_H */
+# if HAVE_NDIR_H
+#  include <ndir.h>
+# endif /* HAVE_NDIR_H */
+#endif /* HAVE_DIRENT_H */
+'
+  AC_CHECK_FUNCS(dirfd)
+  AC_CHECK_DECLS([dirfd], , , $dirfd_headers)
+
+  AC_CACHE_CHECK([whether dirfd is a macro],
+    jm_cv_func_dirfd_macro,
+    [AC_EGREP_CPP([dirent_header_defines_dirfd], [$dirfd_headers
+#ifdef dirfd
+ dirent_header_defines_dirfd
+#endif],
+       jm_cv_func_dirfd_macro=yes,
+       jm_cv_func_dirfd_macro=no)])
+
+  # Use the replacement only if we have no function, macro,
+  # or declaration with that name.
+  if test $ac_cv_func_dirfd,$ac_cv_have_decl_dirfd,$jm_cv_func_dirfd_macro \
+      = no,no,no; then
+    AC_REPLACE_FUNCS([dirfd])
+    AC_CACHE_CHECK(
+	      [how to get the file descriptor associated with an open DIR*],
+		   gl_cv_sys_dir_fd_member_name,
+      [
+        dirfd_save_CFLAGS=$CFLAGS
+	for ac_expr in d_fd dd_fd; do
+
+	  CFLAGS="$CFLAGS -DDIR_FD_MEMBER_NAME=$ac_expr"
+	  AC_TRY_COMPILE(
+	    [$dirfd_headers
+	    ],
+	    [DIR *dir_p = opendir("."); (void) dir_p->DIR_FD_MEMBER_NAME;],
+	    dir_fd_found=yes
+	  )
+	  CFLAGS=$dirfd_save_CFLAGS
+	  test "$dir_fd_found" = yes && break
+	done
+	test "$dir_fd_found" = yes || ac_expr=no_such_member
+
+	gl_cv_sys_dir_fd_member_name=$ac_expr
+      ]
+    )
+    if test $gl_cv_sys_dir_fd_member_name != no_such_member; then
+      AC_DEFINE_UNQUOTED(DIR_FD_MEMBER_NAME,
+	$gl_cv_sys_dir_fd_member_name,
+	[the name of the file descriptor member of DIR])
+    fi
+    AH_VERBATIM(DIR_TO_FD,
+		[#ifdef DIR_FD_MEMBER_NAME
+# define DIR_TO_FD(Dir_p) ((Dir_p)->DIR_FD_MEMBER_NAME)
+#else
+# define DIR_TO_FD(Dir_p) -1
+#endif
+]
+    )
+  fi
+])
+
+UTILS_FUNC_DIRFD
+
+#
+# iconv
+#
+
+dnl This macros shamelessly stolen from
+dnl http://gcc.gnu.org/ml/gcc-bugs/2001-06/msg01398.html.
+dnl Written by Bruno Haible.
+
+AC_DEFUN([UTILS_FUNC_ICONV],
+[
+  dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
+  dnl those with the standalone portable GNU libiconv installed).
+
+  AC_ARG_WITH([libiconv-prefix],
+[  --with-libiconv-prefix=DIR  search for libiconv in DIR/include and DIR/lib], [
+    for dir in `echo "$withval" | tr : ' '`; do
+      if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi
+      if test -d $dir/lib; then LDFLAGS="$LDFLAGS -L$dir/lib"; fi
+    done
+   ])
+  AC_CHECK_HEADER(iconv.h, AC_DEFINE(HAVE_ICONV_H))
+
+  AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
+    am_cv_func_iconv="no, consider installing GNU libiconv"
+    am_cv_lib_iconv=no
+    AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+      [iconv_t cd = iconv_open("","");
+       iconv(cd,NULL,NULL,NULL,NULL);
+       iconv_close(cd);],
+      am_cv_func_iconv=yes)
+    if test "$am_cv_func_iconv" != yes; then
+      am_save_LIBS="$LIBS"
+      LIBS="$LIBS -liconv"
+      AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+        [iconv_t cd = iconv_open("","");
+         iconv(cd,NULL,NULL,NULL,NULL);
+         iconv_close(cd);],
+        am_cv_lib_iconv=yes
+        am_cv_func_iconv=yes)
+      LIBS="$am_save_LIBS"
+    fi
+  ])
+  if test "$am_cv_func_iconv" = yes; then
+    AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
+    AC_MSG_CHECKING([for iconv declaration])
+    AC_CACHE_VAL(am_cv_proto_iconv, [
+      AC_TRY_COMPILE([
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
+      am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+    am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+    AC_MSG_RESULT([$]{ac_t:-
+         }[$]am_cv_proto_iconv)
+    AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
+      [Define as const if the declaration of iconv() needs const.])
+  fi
+  LIBICONV=
+  if test "$am_cv_lib_iconv" = yes; then
+    LIBICONV="-liconv"
+  fi
+  AC_SUBST(LIBICONV)
+])
+
+UTILS_FUNC_ICONV
+LIBS="$LIBS $LIBICONV"
+
+#
+# socklen_t
+# from curl
+
+dnl Check for socklen_t: historically on BSD it is an int, and in
+dnl POSIX 1g it is a type of its own, but some platforms use different
+dnl types for the argument to getsockopt, getpeername, etc.  So we
+dnl have to test to find something that will work.
+AC_DEFUN([TYPE_SOCKLEN_T],
+[
+   AC_CHECK_TYPE([socklen_t], ,[
+      AC_MSG_CHECKING([for socklen_t equivalent])
+      AC_CACHE_VAL([socklen_t_cv_equiv],
+      [
+         # Systems have either "struct sockaddr *" or
+         # "void *" as the second argument to getpeername
+         socklen_t_cv_equiv=
+         for arg2 in "struct sockaddr" void; do
+            for t in int size_t unsigned long "unsigned long"; do
+               AC_TRY_COMPILE([
+                  #include <sys/types.h>
+                  #include <sys/socket.h>
+
+                  int getpeername (int, $arg2 *, $t *);
+               ],[
+                  $t len;
+                  getpeername(0,0,&len);
+               ],[
+                  socklen_t_cv_equiv="$t"
+                  break
+               ])
+            done
+         done
+
+         if test "x$socklen_t_cv_equiv" = x; then
+            AC_MSG_ERROR([Cannot find a type to use in place of socklen_t])
+         fi
+      ])
+      AC_MSG_RESULT($socklen_t_cv_equiv)
+      AC_DEFINE_UNQUOTED(socklen_t, $socklen_t_cv_equiv,
+			[type to use in place of socklen_t if not defined])],
+      [#include <sys/types.h>
+#include <sys/socket.h>])
+])
+
+TYPE_SOCKLEN_T
+
+#
+# statfs stuff
+#
+AC_CHECK_HEADERS(sys/vfs.h)
+AC_CHECK_HEADERS(sys/statvfs.h)
+AC_CHECK_HEADERS(sys/statfs.h)
+AC_CHECK_HEADERS(sys/param.h)
+
+mount_includes="\
+  $ac_includes_default
+  #if HAVE_SYS_PARAM_H
+  # include <sys/param.h>
+  #endif
+  "
+
+AC_CHECK_HEADERS(sys/mount.h,,,[$mount_includes])
+
+#################################################
+# these tests are taken from the GNU fileutils package
+AC_CHECKING(how to get filesystem space usage)
+space=no
+
+# Test for statvfs64.
+if test $space = no; then
+  # SVR4
+  AC_CACHE_CHECK([statvfs64 function (SVR4)], fu_cv_sys_stat_statvfs64,
+  [AC_TRY_RUN([
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/statvfs.h>
+  main ()
+  {
+    struct statvfs64 fsd;
+    exit (statvfs64 (".", &fsd));
+  }],
+  fu_cv_sys_stat_statvfs64=yes,
+  fu_cv_sys_stat_statvfs64=no,
+  fu_cv_sys_stat_statvfs64=cross)])
+  if test $fu_cv_sys_stat_statvfs64 = yes; then
+    space=yes
+    AC_DEFINE(STAT_STATVFS64,1,[Whether statvfs64() is available])
+  fi
+fi
+
+# Perform only the link test since it seems there are no variants of the
+# statvfs function.  This check is more than just AC_CHECK_FUNCS(statvfs)
+# because that got a false positive on SCO OSR5.  Adding the declaration
+# of a `struct statvfs' causes this test to fail (as it should) on such
+# systems.  That system is reported to work fine with STAT_STATFS4 which
+# is what it gets when this test fails.
+if test $space = no; then
+  # SVR4
+  AC_CACHE_CHECK([statvfs function (SVR4)], fu_cv_sys_stat_statvfs,
+                 [AC_TRY_LINK([#include <sys/types.h>
+#include <sys/statvfs.h>],
+                              [struct statvfs fsd; statvfs (0, &fsd);],
+                              fu_cv_sys_stat_statvfs=yes,
+                              fu_cv_sys_stat_statvfs=no)])
+  if test $fu_cv_sys_stat_statvfs = yes; then
+    space=yes
+    AC_DEFINE(STAT_STATVFS,1,[Whether statvfs() is available])
+  fi
+fi
+
+if test $space = no; then
+  # DEC Alpha running OSF/1
+  AC_MSG_CHECKING([for 3-argument statfs function (DEC OSF/1)])
+  AC_CACHE_VAL(fu_cv_sys_stat_statfs3_osf1,
+  [AC_TRY_RUN([
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+  main ()
+  {
+    struct statfs fsd;
+    fsd.f_fsize = 0;
+    exit (statfs (".", &fsd, sizeof (struct statfs)));
+  }],
+  fu_cv_sys_stat_statfs3_osf1=yes,
+  fu_cv_sys_stat_statfs3_osf1=no,
+  fu_cv_sys_stat_statfs3_osf1=no)])
+
+
+#C_MSG_RESULT($fu_cv_sys_stat_statfs3_osf1)
+  if test $fu_cv_sys_stat_statfs3_osf1 = yes; then
+    space=yes
+    AC_DEFINE(STAT_STATFS3_OSF1,1,[Whether statfs requires 3 arguments])
+  fi
+fi
+
+if test $space = no; then
+# AIX
+  AC_MSG_CHECKING([for two-argument statfs with statfs.bsize dnl
+member (AIX, 4.3BSD)])
+  AC_CACHE_VAL(fu_cv_sys_stat_statfs2_bsize,
+  [AC_TRY_RUN([
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+  main ()
+  {
+  struct statfs fsd;
+  fsd.f_bsize = 0;
+  exit (statfs (".", &fsd));
+  }],
+  fu_cv_sys_stat_statfs2_bsize=yes,
+  fu_cv_sys_stat_statfs2_bsize=no,
+  fu_cv_sys_stat_statfs2_bsize=no)])
+  AC_MSG_RESULT($fu_cv_sys_stat_statfs2_bsize)
+  if test $fu_cv_sys_stat_statfs2_bsize = yes; then
+    space=yes
+    AC_DEFINE(STAT_STATFS2_BSIZE,1,[Whether statfs requires two arguments and struct statfs has bsize property])
+  fi
+fi
+
+if test $space = no; then
+# SVR3
+  AC_MSG_CHECKING([for four-argument statfs (AIX-3.2.5, SVR3)])
+  AC_CACHE_VAL(fu_cv_sys_stat_statfs4,
+  [AC_TRY_RUN([#include <sys/types.h>
+#include <sys/statfs.h>
+  main ()
+  {
+  struct statfs fsd;
+  exit (statfs (".", &fsd, sizeof fsd, 0));
+  }],
+    fu_cv_sys_stat_statfs4=yes,
+    fu_cv_sys_stat_statfs4=no,
+    fu_cv_sys_stat_statfs4=no)])
+  AC_MSG_RESULT($fu_cv_sys_stat_statfs4)
+  if test $fu_cv_sys_stat_statfs4 = yes; then
+    space=yes
+    AC_DEFINE(STAT_STATFS4,1,[Whether statfs requires 4 arguments])
+  fi
+fi
+
+if test $space = no; then
+# 4.4BSD and NetBSD
+  AC_MSG_CHECKING([for two-argument statfs with statfs.fsize dnl
+member (4.4BSD and NetBSD)])
+  AC_CACHE_VAL(fu_cv_sys_stat_statfs2_fsize,
+  [AC_TRY_RUN([#include <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+  main ()
+  {
+  struct statfs fsd;
+  fsd.f_fsize = 0;
+  exit (statfs (".", &fsd));
+  }],
+  fu_cv_sys_stat_statfs2_fsize=yes,
+  fu_cv_sys_stat_statfs2_fsize=no,
+  fu_cv_sys_stat_statfs2_fsize=no)])
+  AC_MSG_RESULT($fu_cv_sys_stat_statfs2_fsize)
+  if test $fu_cv_sys_stat_statfs2_fsize = yes; then
+    space=yes
+        AC_DEFINE(STAT_STATFS2_FSIZE,1,[Whether statfs requires 2 arguments and struct statfs has fsize])
+  fi
+fi
+
+if test $space = no; then
+  # Ultrix
+  AC_MSG_CHECKING([for two-argument statfs with struct fs_data (Ultrix)])
+  AC_CACHE_VAL(fu_cv_sys_stat_fs_data,
+  [AC_TRY_RUN([#include <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+#ifdef HAVE_SYS_FS_TYPES_H
+#include <sys/fs_types.h>
+#endif
+  main ()
+  {
+  struct fs_data fsd;
+  /* Ultrix's statfs returns 1 for success,
+     0 for not mounted, -1 for failure.  */
+  exit (statfs (".", &fsd) != 1);
+  }],
+  fu_cv_sys_stat_fs_data=yes,
+  fu_cv_sys_stat_fs_data=no,
+  fu_cv_sys_stat_fs_data=no)])
+  AC_MSG_RESULT($fu_cv_sys_stat_fs_data)
+  if test $fu_cv_sys_stat_fs_data = yes; then
+    space=yes
+    AC_DEFINE(STAT_STATFS2_FS_DATA,1,[Whether statfs requires 2 arguments and struct fs_data is available])
+  fi
+fi
+
+  statxfs_includes="\
+$ac_includes_default
+#if HAVE_SYS_STATVFS_H
+# include <sys/statvfs.h>
+#endif
+#if HAVE_SYS_VFS_H
+# include <sys/vfs.h>
+#endif
+#if !HAVE_SYS_STATVFS_H && !HAVE_SYS_VFS_H
+# if HAVE_SYS_MOUNT_H && HAVE_SYS_PARAM_H
+/* NetBSD 1.5.2 needs these, for the declaration of struct statfs. */
+#  include <sys/param.h>
+#  include <sys/mount.h>
+# elif HAVE_NETINET_IN_H && HAVE_NFS_NFS_CLNT_H && HAVE_NFS_VFS_H
+/* Ultrix 4.4 needs these for the declaration of struct statfs.  */
+#  include <netinet/in.h>
+#  include <nfs/nfs_clnt.h>
+#  include <nfs/vfs.h>
+# endif
+#endif
+"
+
+AC_CHECK_MEMBERS([struct statfs.f_namemax],,,[$statxfs_includes])
+AC_CHECK_MEMBERS([struct statvfs.f_namemax],,,[$statxfs_includes])
+AC_CHECK_MEMBERS([struct statfs.f_namelen],,,[$statxfs_includes])
+AC_CHECK_MEMBERS([struct statvfs.f_namelen],,,[$statxfs_includes])
+
+#
+# Large file support
+#
+AC_SYS_LARGEFILE
+
+#
+# mntent
+#
+AC_CHECK_HEADER(mntent.h, AC_DEFINE(HAVE_MNTENT_H))
+AC_CHECK_FUNCS(setmntent)
+
+#
+# IPv6
+#
+AC_ARG_WITH(ipv6,
+    [  --with-ipv6             enable IPv6-support],
+    [ 
+        if test $withval != "no";
+        then
+	    AC_DEFINE(IPv6,1)
+	fi
+    ])
+
+
+#
+# debugging
+#
+AC_ARG_WITH(debug,
+    [  --with-debug            enable protocol debugging output],
+    [
+        if test $withval != "no";
+        then 
+            AC_DEFINE(WITH_DEBUG,1)
+	fi
+    ])
+
+AC_ARG_WITH(debug-kbd,
+    [  --with-debug-kbd        enable debugging of keyboard handling],
+    [
+        if test $withval != "no";
+        then 
+            AC_DEFINE(WITH_DEBUG_KBD,1)
+	fi
+    ])
+
+AC_ARG_WITH(debug-rdp5,
+    [  --with-debug-rdp5       enable debugging of RDP5 code],
+    [
+        if test $withval != "no";
+        then 
+            AC_DEFINE(WITH_DEBUG_RDP5,1)
+	fi
+    ])
+
+AC_ARG_WITH(debug-clipboard,
+    [  --with-debug-clipboard  enable debugging of clipboard code],
+    [
+        if test $withval != "no";
+        then 
+            AC_DEFINE(WITH_DEBUG_CLIPBOARD,1)
+	fi
+    ])
+
+AC_ARG_WITH(debug-sound,
+    [  --with-debug-sound  enable debugging of sound code],
+    [
+        if test $withval != "no";
+        then 
+            AC_DEFINE(WITH_DEBUG_SOUND,1)
+	fi
+    ])
+
+AC_ARG_WITH(debug-channel,
+    [  --with-debug-channel  enable debugging of virtual channel code],
+    [
+        if test $withval != "no";
+        then 
+            AC_DEFINE(WITH_DEBUG_CHANNEL,1)
+	fi
+    ])
+
+AC_ARG_WITH(debug-seamless,
+    [  --with-debug-seamless  enable debugging of SeamlessRDP code],
+    [
+        if test $withval != "no";
+        then 
+            AC_DEFINE(WITH_DEBUG_SEAMLESS,1)
+	fi
+    ])
+
+AC_ARG_WITH(debug-smartcard,
+    [  --with-debug-smartcard  enable debugging of smart-card code],
+    [
+        if test $withval != "no";
+        then
+		if test x"$WITH_SCARD" = "x1"; then
+			AC_DEFINE(WITH_DEBUG_SCARD,1)
+		fi
+	fi
+    ])
+
+AC_ARG_WITH(debug-credssp,
+    [  --with-debug-credssp	enable debugging of CredSSP code],
+    [
+	if test $withval != "no";
+	then
+		if test x"$WITH_CREDSSP" = "x1"; then
+		   AC_DEFINE(WITH_DEBUG_CREDSSP,1)
+		fi
+	fi
+    ])
+
+#
+# target-specific stuff
+#
+case "$host" in
+*-*-hpux*)
+    CFLAGS="$CFLAGS -D_XOPEN_SOURCE_EXTENDED"
+    ;;
+*-*-irix6.5*)
+    LIBS="-L$ssldir/lib32 $LIBS"
+    CFLAGS="$CFLAGS -D__SGI_IRIX__"
+    ;;
+esac
+
+AC_OUTPUT(Makefile)
+
+dnl Local Variables:
+dnl comment-start: "dnl "
+dnl comment-end: ""
+dnl comment-start-skip: "\\bdnl\\b\\s *"
+dnl compile-command: "autoconf"
+dnl End:
Index: /trunk/src/VBox/RDP/client-1.8.3/constants.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/constants.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/constants.h	(revision 55121)
@@ -0,0 +1,545 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   Miscellaneous protocol constants
+   Copyright (C) Matthew Chapman 1999-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* TCP port for Remote Desktop Protocol */
+#define TCP_PORT_RDP 3389
+
+#define DEFAULT_CODEPAGE	"UTF-8"
+#define WINDOWS_CODEPAGE	"UTF-16LE"
+
+/* ISO PDU codes */
+enum ISO_PDU_CODE
+{
+	ISO_PDU_CR = 0xE0,	/* Connection Request */
+	ISO_PDU_CC = 0xD0,	/* Connection Confirm */
+	ISO_PDU_DR = 0x80,	/* Disconnect Request */
+	ISO_PDU_DT = 0xF0,	/* Data */
+	ISO_PDU_ER = 0x70	/* Error */
+};
+
+/* RDP protocol negotiating constants */
+enum RDP_NEG_TYPE_CODE
+{
+	RDP_NEG_REQ = 1,
+	RDP_NEG_RSP = 2,
+	RDP_NEG_FAILURE = 3
+};
+
+enum RDP_NEG_REQ_CODE
+{
+	PROTOCOL_RDP = 0,
+	PROTOCOL_SSL = 1,
+	PROTOCOL_HYBRID = 2
+};
+
+enum RDP_NEG_FAILURE_CODE
+{
+	SSL_REQUIRED_BY_SERVER = 1,
+	SSL_NOT_ALLOWED_BY_SERVER = 2,
+	SSL_CERT_NOT_ON_SERVER = 3,
+	INCONSISTENT_FLAGS = 4,
+	HYBRID_REQUIRED_BY_SERVER = 5,
+	SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER = 6
+};
+
+/* MCS PDU codes */
+enum MCS_PDU_TYPE
+{
+	MCS_EDRQ = 1,		/* Erect Domain Request */
+	MCS_DPUM = 8,		/* Disconnect Provider Ultimatum */
+	MCS_AURQ = 10,		/* Attach User Request */
+	MCS_AUCF = 11,		/* Attach User Confirm */
+	MCS_CJRQ = 14,		/* Channel Join Request */
+	MCS_CJCF = 15,		/* Channel Join Confirm */
+	MCS_SDRQ = 25,		/* Send Data Request */
+	MCS_SDIN = 26		/* Send Data Indication */
+};
+
+#define MCS_CONNECT_INITIAL	0x7f65
+#define MCS_CONNECT_RESPONSE	0x7f66
+
+#define BER_TAG_BOOLEAN		1
+#define BER_TAG_INTEGER		2
+#define BER_TAG_OCTET_STRING	4
+#define BER_TAG_RESULT		10
+#define BER_TAG_SEQUENCE	16
+#define BER_TAG_CONSTRUCTED	0x20
+#define BER_TAG_CTXT_SPECIFIC	0x80
+
+#define MCS_TAG_DOMAIN_PARAMS	0x30
+
+#define MCS_GLOBAL_CHANNEL	1003
+#define MCS_USERCHANNEL_BASE    1001
+
+/* RDP secure transport constants */
+#define SEC_RANDOM_SIZE		32
+#define SEC_MODULUS_SIZE	64
+#define SEC_MAX_MODULUS_SIZE	256
+#define SEC_PADDING_SIZE	8
+#define SEC_EXPONENT_SIZE	4
+
+#define SEC_CLIENT_RANDOM	0x0001
+#define SEC_ENCRYPT		0x0008
+#define SEC_LOGON_INFO		0x0040
+#define SEC_LICENCE_NEG		0x0080
+#define SEC_REDIRECT_ENCRYPT	0x0C00
+
+#define SEC_TAG_SRV_INFO	0x0c01
+#define SEC_TAG_SRV_CRYPT	0x0c02
+#define SEC_TAG_SRV_CHANNELS	0x0c03
+
+#define SEC_TAG_CLI_INFO	0xc001
+#define SEC_TAG_CLI_CRYPT	0xc002
+#define SEC_TAG_CLI_CHANNELS    0xc003
+#define SEC_TAG_CLI_CLUSTER     0xc004
+
+#define SEC_TAG_PUBKEY		0x0006
+#define SEC_TAG_KEYSIG		0x0008
+
+#define SEC_RSA_MAGIC		0x31415352	/* RSA1 */
+
+/* Client cluster constants */
+#define SEC_CC_REDIRECTION_SUPPORTED          0x00000001
+#define SEC_CC_REDIRECT_SESSIONID_FIELD_VALID 0x00000002
+#define SEC_CC_REDIRECTED_SMARTCARD           0x00000040
+#define SEC_CC_REDIRECT_VERSION_MASK          0x0000003c
+
+#define SEC_CC_REDIRECT_VERSION_3             0x02
+#define SEC_CC_REDIRECT_VERSION_4             0x03
+#define SEC_CC_REDIRECT_VERSION_5             0x04
+#define SEC_CC_REDIRECT_VERSION_6             0x05
+
+/* RDP licensing constants */
+#define LICENCE_TOKEN_SIZE	10
+#define LICENCE_HWID_SIZE	20
+#define LICENCE_SIGNATURE_SIZE	16
+
+#define LICENCE_TAG_REQUEST                     0x01
+#define LICENCE_TAG_PLATFORM_CHALLANGE          0x02
+#define LICENCE_TAG_NEW_LICENCE                 0x03
+#define LICENCE_TAG_UPGRADE_LICENCE             0x04
+#define LICENCE_TAG_LICENCE_INFO                0x12
+#define LICENCE_TAG_NEW_LICENCE_REQUEST         0x13
+#define LICENCE_TAG_PLATFORM_CHALLANGE_RESPONSE 0x15
+#define LICENCE_TAG_ERROR_ALERT                 0xff
+
+#define BB_CLIENT_USER_NAME_BLOB	0x000f
+#define BB_CLIENT_MACHINE_NAME_BLOB	0x0010
+
+/* RDP PDU codes */
+enum RDP_PDU_TYPE
+{
+	RDP_PDU_DEMAND_ACTIVE = 1,
+	RDP_PDU_CONFIRM_ACTIVE = 3,
+	RDP_PDU_REDIRECT = 4,	/* Standard Server Redirect */
+	RDP_PDU_DEACTIVATE = 6,
+	RDP_PDU_DATA = 7,
+	RDP_PDU_ENHANCED_REDIRECT = 10	/* Enhanced Server Redirect */
+};
+
+enum RDP_DATA_PDU_TYPE
+{
+	RDP_DATA_PDU_UPDATE = 2,
+	RDP_DATA_PDU_CONTROL = 20,
+	RDP_DATA_PDU_POINTER = 27,
+	RDP_DATA_PDU_INPUT = 28,
+	RDP_DATA_PDU_SYNCHRONISE = 31,
+	RDP_DATA_PDU_BELL = 34,
+	RDP_DATA_PDU_CLIENT_WINDOW_STATUS = 35,
+	RDP_DATA_PDU_LOGON = 38,	/* PDUTYPE2_SAVE_SESSION_INFO */
+	RDP_DATA_PDU_FONT2 = 39,
+	RDP_DATA_PDU_KEYBOARD_INDICATORS = 41,
+	RDP_DATA_PDU_DISCONNECT = 47,
+	RDP_DATA_PDU_AUTORECONNECT_STATUS = 50
+};
+
+enum RDP_SAVE_SESSION_PDU_TYPE
+{
+	INFOTYPE_LOGON = 0,
+	INFOTYPE_LOGON_LONG = 1,
+	INFOTYPE_LOGON_PLAINNOTIFY = 2,
+	INFOTYPE_LOGON_EXTENDED_INF = 3
+};
+
+enum RDP_LOGON_INFO_EXTENDED_TYPE
+{
+	LOGON_EX_AUTORECONNECTCOOKIE = 1,
+	LOGON_EX_LOGONERRORS = 2
+};
+
+enum RDP_CONTROL_PDU_TYPE
+{
+	RDP_CTL_REQUEST_CONTROL = 1,
+	RDP_CTL_GRANT_CONTROL = 2,
+	RDP_CTL_DETACH = 3,
+	RDP_CTL_COOPERATE = 4
+};
+
+enum RDP_UPDATE_PDU_TYPE
+{
+	RDP_UPDATE_ORDERS = 0,
+	RDP_UPDATE_BITMAP = 1,
+	RDP_UPDATE_PALETTE = 2,
+	RDP_UPDATE_SYNCHRONIZE = 3
+};
+
+enum RDP_POINTER_PDU_TYPE
+{
+	RDP_POINTER_SYSTEM = 1,
+	RDP_POINTER_MOVE = 3,
+	RDP_POINTER_COLOR = 6,
+	RDP_POINTER_CACHED = 7,
+	RDP_POINTER_NEW = 8
+};
+
+enum RDP_SYSTEM_POINTER_TYPE
+{
+	RDP_NULL_POINTER = 0,
+	RDP_DEFAULT_POINTER = 0x7F00
+};
+
+enum RDP_INPUT_DEVICE
+{
+	RDP_INPUT_SYNCHRONIZE = 0,
+	RDP_INPUT_CODEPOINT = 1,
+	RDP_INPUT_VIRTKEY = 2,
+	RDP_INPUT_SCANCODE = 4,
+	RDP_INPUT_MOUSE = 0x8001
+};
+
+/* Device flags */
+#define KBD_FLAG_RIGHT          0x0001
+#define KBD_FLAG_EXT            0x0100
+#define KBD_FLAG_QUIET          0x1000
+#define KBD_FLAG_DOWN           0x4000
+#define KBD_FLAG_UP             0x8000
+
+/* These are for synchronization; not for keystrokes */
+#define KBD_FLAG_SCROLL   0x0001
+#define KBD_FLAG_NUMLOCK  0x0002
+#define KBD_FLAG_CAPITAL  0x0004
+
+/* See T.128 */
+#define RDP_KEYPRESS 0
+#define RDP_KEYRELEASE (KBD_FLAG_DOWN | KBD_FLAG_UP)
+
+#define MOUSE_FLAG_MOVE         0x0800
+#define MOUSE_FLAG_BUTTON1      0x1000
+#define MOUSE_FLAG_BUTTON2      0x2000
+#define MOUSE_FLAG_BUTTON3      0x4000
+#define MOUSE_FLAG_BUTTON4      0x0280
+#define MOUSE_FLAG_BUTTON5      0x0380
+#define MOUSE_FLAG_DOWN         0x8000
+
+/* Raster operation masks */
+#define ROP2_S(rop3) (rop3 & 0xf)
+#define ROP2_P(rop3) ((rop3 & 0x3) | ((rop3 & 0x30) >> 2))
+
+#define ROP2_COPY	0xc
+#define ROP2_XOR	0x6
+#define ROP2_AND	0x8
+#define ROP2_NXOR	0x9
+#define ROP2_OR		0xe
+
+#define MIX_TRANSPARENT	0
+#define MIX_OPAQUE	1
+
+#define TEXT2_VERTICAL		0x04
+#define TEXT2_IMPLICIT_X	0x20
+
+#define ALTERNATE	1
+#define WINDING		2
+
+/* RDP bitmap cache (version 2) constants */
+#define BMPCACHE2_C0_CELLS	0x78
+#define BMPCACHE2_C1_CELLS	0x78
+#define BMPCACHE2_C2_CELLS	0x150
+#define BMPCACHE2_NUM_PSTCELLS	0x9f6
+
+#define PDU_FLAG_FIRST		0x01
+#define PDU_FLAG_LAST		0x02
+
+/* RDP capabilities */
+#define RDP_CAPSET_GENERAL	1	/* Maps to generalCapabilitySet in T.128 page 138 */
+#define RDP_CAPLEN_GENERAL	0x18
+#define OS_MAJOR_TYPE_UNIX	4
+#define OS_MINOR_TYPE_XSERVER	7
+
+#define RDP_CAPSET_BITMAP	2
+#define RDP_CAPLEN_BITMAP	0x1C
+
+#define RDP_CAPSET_ORDER	3
+#define RDP_CAPLEN_ORDER	0x58
+#define ORDER_CAP_NEGOTIATE	2
+#define ORDER_CAP_NOSUPPORT	4
+
+#define RDP_CAPSET_BMPCACHE	4
+#define RDP_CAPLEN_BMPCACHE	0x28
+
+#define RDP_CAPSET_CONTROL	5
+#define RDP_CAPLEN_CONTROL	0x0C
+
+#define RDP_CAPSET_ACTIVATE	7
+#define RDP_CAPLEN_ACTIVATE	0x0C
+
+#define RDP_CAPSET_POINTER	8
+#define RDP_CAPLEN_POINTER	0x08
+#define RDP_CAPLEN_NEWPOINTER	0x0a
+
+#define RDP_CAPSET_SHARE	9
+#define RDP_CAPLEN_SHARE	0x08
+
+#define RDP_CAPSET_COLCACHE	10
+#define RDP_CAPLEN_COLCACHE	0x08
+
+#define RDP_CAPSET_BRUSHCACHE	15
+#define RDP_CAPLEN_BRUSHCACHE	0x08
+
+#define RDP_CAPSET_BMPCACHE2	19
+#define RDP_CAPLEN_BMPCACHE2	0x28
+#define BMPCACHE2_FLAG_PERSIST	((uint32)1<<31)
+
+#define RDP_SOURCE		"MSTSC"
+
+/* Logon flags */
+#define RDP_INFO_MOUSE                0x00000001
+#define RDP_INFO_DISABLECTRLALTDEL    0x00000002
+#define RDP_INFO_AUTOLOGON 	      0x00000008
+#define RDP_INFO_UNICODE              0x00000010
+#define RDP_INFO_MAXIMIZESHELL        0x00000020
+#define RDP_INFO_COMPRESSION	      0x00000080	/* mppc compression with 8kB histroy buffer */
+#define RDP_INFO_ENABLEWINDOWSKEY     0x00000100
+#define RDP_INFO_COMPRESSION2	      0x00000200	/* rdp5 mppc compression with 64kB history buffer */
+#define RDP_INFO_REMOTE_CONSOLE_AUDIO 0x00002000
+#define RDP_INFO_PASSWORD_IS_SC_PIN   0x00040000
+
+#define RDP5_DISABLE_NOTHING	0x00
+#define RDP5_NO_WALLPAPER	0x01
+#define RDP5_NO_FULLWINDOWDRAG	0x02
+#define RDP5_NO_MENUANIMATIONS	0x04
+#define RDP5_NO_THEMING		0x08
+#define RDP5_NO_CURSOR_SHADOW	0x20
+#define RDP5_NO_CURSORSETTINGS	0x40	/* disables cursor blinking */
+
+/* compression types */
+#define RDP_MPPC_BIG		0x01
+#define RDP_MPPC_COMPRESSED	0x20
+#define RDP_MPPC_RESET		0x40
+#define RDP_MPPC_FLUSH		0x80
+#define RDP_MPPC_DICT_SIZE      65536
+
+#define RDP5_COMPRESSED		0x80
+
+/* Keymap flags */
+#define MapRightShiftMask   (1<<0)
+#define MapLeftShiftMask    (1<<1)
+#define MapShiftMask (MapRightShiftMask | MapLeftShiftMask)
+
+#define MapRightAltMask     (1<<2)
+#define MapLeftAltMask      (1<<3)
+#define MapAltGrMask MapRightAltMask
+
+#define MapRightCtrlMask    (1<<4)
+#define MapLeftCtrlMask     (1<<5)
+#define MapCtrlMask (MapRightCtrlMask | MapLeftCtrlMask)
+
+#define MapRightWinMask     (1<<6)
+#define MapLeftWinMask      (1<<7)
+#define MapWinMask (MapRightWinMask | MapLeftWinMask)
+
+#define MapNumLockMask      (1<<8)
+#define MapCapsLockMask     (1<<9)
+
+#define MapLocalStateMask   (1<<10)
+
+#define MapInhibitMask      (1<<11)
+
+#define MASK_ADD_BITS(var, mask) (var |= mask)
+#define MASK_REMOVE_BITS(var, mask) (var &= ~mask)
+#define MASK_HAS_BITS(var, mask) ((var & mask)>0)
+#define MASK_CHANGE_BIT(var, mask, active) (var = ((var & ~mask) | (active ? mask : 0)))
+
+/* Clipboard constants, "borrowed" from GCC system headers in 
+   the w32 cross compiler
+   this is the CF_ set when WINVER is 0x0400 */
+
+#ifndef CF_TEXT
+#define CF_TEXT         1
+#define CF_BITMAP       2
+#define CF_METAFILEPICT 3
+#define CF_SYLK         4
+#define CF_DIF          5
+#define CF_TIFF         6
+#define CF_OEMTEXT      7
+#define CF_DIB          8
+#define CF_PALETTE      9
+#define CF_PENDATA      10
+#define CF_RIFF         11
+#define CF_WAVE         12
+#define CF_UNICODETEXT  13
+#define CF_ENHMETAFILE  14
+#define CF_HDROP        15
+#define CF_LOCALE       16
+#define CF_MAX          17
+#define CF_OWNERDISPLAY 128
+#define CF_DSPTEXT      129
+#define CF_DSPBITMAP    130
+#define CF_DSPMETAFILEPICT      131
+#define CF_DSPENHMETAFILE       142
+#define CF_PRIVATEFIRST 512
+#define CF_PRIVATELAST  767
+#define CF_GDIOBJFIRST  768
+#define CF_GDIOBJLAST   1023
+#endif
+
+/* Sound format constants */
+#define WAVE_FORMAT_PCM		1
+#define WAVE_FORMAT_ADPCM	2
+#define WAVE_FORMAT_ALAW	6
+#define WAVE_FORMAT_MULAW	7
+
+/* Virtual channel options */
+#define CHANNEL_OPTION_INITIALIZED	0x80000000
+#define CHANNEL_OPTION_ENCRYPT_RDP	0x40000000
+#define CHANNEL_OPTION_COMPRESS_RDP	0x00800000
+#define CHANNEL_OPTION_SHOW_PROTOCOL	0x00200000
+
+/* NT status codes for RDPDR */
+#define RD_STATUS_SUCCESS                  0x00000000
+#define RD_STATUS_NOT_IMPLEMENTED          0x00000001
+#define RD_STATUS_PENDING                  0x00000103
+
+#define RD_STATUS_NO_MORE_FILES            0x80000006
+#define RD_STATUS_DEVICE_PAPER_EMPTY       0x8000000e
+#define RD_STATUS_DEVICE_POWERED_OFF       0x8000000f
+#define RD_STATUS_DEVICE_OFF_LINE          0x80000010
+#define RD_STATUS_DEVICE_BUSY              0x80000011
+
+#define RD_STATUS_INVALID_HANDLE           0xc0000008
+#define RD_STATUS_INVALID_PARAMETER        0xc000000d
+#define RD_STATUS_NO_SUCH_FILE             0xc000000f
+#define RD_STATUS_INVALID_DEVICE_REQUEST   0xc0000010
+#define RD_STATUS_ACCESS_DENIED            0xc0000022
+#define RD_STATUS_OBJECT_NAME_COLLISION    0xc0000035
+#define RD_STATUS_DISK_FULL                0xc000007f
+#define RD_STATUS_FILE_IS_A_DIRECTORY      0xc00000ba
+#define RD_STATUS_NOT_SUPPORTED            0xc00000bb
+#define RD_STATUS_TIMEOUT                  0xc0000102
+#define RD_STATUS_NOTIFY_ENUM_DIR          0xc000010c
+#define RD_STATUS_CANCELLED                0xc0000120
+#define RD_STATUS_DIRECTORY_NOT_EMPTY      0xc0000101
+
+/* RDPSND constants */
+#define TSSNDCAPS_ALIVE                    0x00000001
+#define TSSNDCAPS_VOLUME                   0x00000002
+
+/* RDPDR constants */
+
+#define RDPDR_CTYP_CORE                 0x4472
+#define RDPDR_CTYP_PRN                  0x5052
+
+#define PAKID_CORE_SERVER_ANNOUNCE      0x496e
+#define PAKID_CORE_CLIENTID_CONFIRM     0x4343
+#define PAKID_CORE_CLIENT_NAME          0x434e
+#define PAKID_CORE_DEVICE_LIST_ANNOUNCE 0x4441
+#define PAKID_CORE_DEVICE_REPLY         0x6472
+#define PAKID_CORE_DEVICE_IOREQUEST     0x4952
+#define PAKID_CORE_DEVICE_IOCOMPLETION  0x4943
+#define PAKID_CORE_SERVER_CAPABILITY    0x5350
+#define PAKID_CORE_CLIENT_CAPABILITY    0x4350
+#define PAKID_CORE_DEVICELIST_REMOVE    0x444d
+#define PAKID_PRN_CACHE_DATA            0x5043
+#define PAKID_CORE_USER_LOGGEDON        0x554c
+#define PAKID_PRN_USING_XPS             0x5543
+
+#define RDPDR_MAX_DEVICES               0x10
+#define DEVICE_TYPE_SERIAL              0x01
+#define DEVICE_TYPE_PARALLEL            0x02
+#define DEVICE_TYPE_PRINTER             0x04
+#define DEVICE_TYPE_DISK                0x08
+#define DEVICE_TYPE_SCARD               0x20
+
+#define FILE_DIRECTORY_FILE             0x00000001
+#define FILE_NON_DIRECTORY_FILE         0x00000040
+#define FILE_COMPLETE_IF_OPLOCKED       0x00000100
+#define FILE_DELETE_ON_CLOSE            0x00001000
+#define FILE_OPEN_FOR_FREE_SPACE_QUERY  0x00800000
+
+/* RDP5 disconnect PDU */
+#define exDiscReasonNoInfo				0x0000
+#define exDiscReasonAPIInitiatedDisconnect		0x0001
+#define exDiscReasonAPIInitiatedLogoff			0x0002
+#define exDiscReasonServerIdleTimeout			0x0003
+#define exDiscReasonServerLogonTimeout			0x0004
+#define exDiscReasonReplacedByOtherConnection		0x0005
+#define exDiscReasonOutOfMemory				0x0006
+#define exDiscReasonServerDeniedConnection		0x0007
+#define exDiscReasonServerDeniedConnectionFips		0x0008
+#define exDiscReasonServerInsufficientPrivileges        0x0009
+#define exDiscReasonServerFreshCredentialsRequired      0x000a
+#define exDiscReasonRPCInitiatedDisconnectByUser        0x000b
+#define exDiscReasonByUser                              0x000c
+#define exDiscReasonLicenseInternal			0x0100
+#define exDiscReasonLicenseNoLicenseServer		0x0101
+#define exDiscReasonLicenseNoLicense			0x0102
+#define exDiscReasonLicenseErrClientMsg			0x0103
+#define exDiscReasonLicenseHwidDoesntMatchLicense	0x0104
+#define exDiscReasonLicenseErrClientLicense		0x0105
+#define exDiscReasonLicenseCantFinishProtocol		0x0106
+#define exDiscReasonLicenseClientEndedProtocol		0x0107
+#define exDiscReasonLicenseErrClientEncryption		0x0108
+#define exDiscReasonLicenseCantUpgradeLicense		0x0109
+#define exDiscReasonLicenseNoRemoteConnections		0x010a
+
+/* SeamlessRDP constants */
+#define SEAMLESSRDP_NOTYETMAPPED -1
+#define SEAMLESSRDP_NORMAL 0
+#define SEAMLESSRDP_MINIMIZED 1
+#define SEAMLESSRDP_MAXIMIZED 2
+#define SEAMLESSRDP_POSITION_TIMER 200000
+
+#define SEAMLESSRDP_CREATE_MODAL	0x0001
+#define SEAMLESSRDP_CREATE_TOPMOST	0x0002
+
+#define SEAMLESSRDP_HELLO_RECONNECT	0x0001
+#define SEAMLESSRDP_HELLO_HIDDEN	0x0002
+
+/* Smartcard constants */
+#define SCARD_LOCK_TCP		0
+#define SCARD_LOCK_SEC		1
+#define SCARD_LOCK_CHANNEL	2
+#define SCARD_LOCK_RDPDR	3
+#define SCARD_LOCK_LAST		4
+
+
+/* redirect flags, from [MS-RDPBCGR] 2.2.13.1 */
+enum RDP_PDU_REDIRECT_FLAGS
+{
+	PDU_REDIRECT_HAS_IP = 0x1,
+	PDU_REDIRECT_HAS_LOAD_BALANCE_INFO = 0x2,
+	PDU_REDIRECT_HAS_USERNAME = 0x4,
+	PDU_REDIRECT_HAS_DOMAIN = 0x8,
+	PDU_REDIRECT_HAS_PASSWORD = 0x10,
+	PDU_REDIRECT_DONT_STORE_USERNAME = 0x20,
+	PDU_REDIRECT_USE_SMARTCARD = 0x40,
+	PDU_REDIRECT_INFORMATIONAL = 0x80,
+	PDU_REDIRECT_HAS_TARGET_FQDN = 0x100,
+	PDU_REDIRECT_HAS_TARGET_NETBIOS = 0x200,
+	PDU_REDIRECT_HAS_TARGET_IP_ARRAY = 0x800
+};
Index: /trunk/src/VBox/RDP/client-1.8.3/cssp.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/cssp.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/cssp.c	(revision 55121)
@@ -0,0 +1,909 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   CredSSP layer and kerberos support.
+   Copyright 2012-2013 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <gssapi/gssapi.h>
+#include "rdesktop.h"
+
+extern RD_BOOL g_use_password_as_pin;
+
+extern char *g_sc_csp_name;
+extern char *g_sc_reader_name;
+extern char *g_sc_card_name;
+extern char *g_sc_container_name;
+
+static gss_OID_desc _gss_spnego_krb5_mechanism_oid_desc =
+	{ 9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };
+
+
+static void
+s_realloc(STREAM s, unsigned int size)
+{
+	unsigned char *data;
+
+	if (s->size >= size)
+		return;
+
+	data = s->data;
+	s->size = size;
+	s->data = xrealloc(data, size);
+	s->p = s->data + (s->p - data);
+	s->end = s->data + (s->end - data);
+	s->iso_hdr = s->data + (s->iso_hdr - data);
+	s->mcs_hdr = s->data + (s->mcs_hdr - data);
+	s->sec_hdr = s->data + (s->sec_hdr - data);
+	s->rdp_hdr = s->data + (s->rdp_hdr - data);
+	s->channel_hdr = s->data + (s->channel_hdr - data);
+}
+
+static void
+s_free(STREAM s)
+{
+	free(s->data);
+	free(s);
+}
+
+static STREAM
+ber_wrap_hdr_data(int tagval, STREAM in)
+{
+	STREAM out;
+	int size = s_length(in) + 16;
+
+	out = xmalloc(sizeof(struct stream));
+	memset(out, 0, sizeof(struct stream));
+	out->data = xmalloc(size);
+	out->size = size;
+	out->p = out->data;
+
+	ber_out_header(out, tagval, s_length(in));
+	out_uint8p(out, in->data, s_length(in));
+	s_mark_end(out);
+
+	return out;
+}
+
+
+static void
+cssp_gss_report_error(OM_uint32 code, char *str, OM_uint32 major_status, OM_uint32 minor_status)
+{
+	OM_uint32 msgctx = 0, ms;
+	gss_buffer_desc status_string;
+
+	error("GSS error [%d:%d:%d]: %s\n", (major_status & 0xff000000) >> 24,	// Calling error
+	      (major_status & 0xff0000) >> 16,	// Routine error
+	      major_status & 0xffff,	// Supplementary info bits
+	      str);
+
+	do
+	{
+		ms = gss_display_status(&minor_status, major_status,
+					code, GSS_C_NULL_OID, &msgctx, &status_string);
+		if (ms != GSS_S_COMPLETE)
+			continue;
+
+		error(" - %s\n", status_string.value);
+
+	}
+	while (ms == GSS_S_COMPLETE && msgctx);
+
+}
+
+
+static RD_BOOL
+cssp_gss_mech_available(gss_OID mech)
+{
+	int mech_found;
+	OM_uint32 major_status, minor_status;
+	gss_OID_set mech_set;
+
+	mech_found = 0;
+
+	if (mech == GSS_C_NO_OID)
+		return True;
+
+	major_status = gss_indicate_mechs(&minor_status, &mech_set);
+	if (!mech_set)
+		return False;
+
+	if (GSS_ERROR(major_status))
+	{
+		cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to get available mechs on system",
+				      major_status, minor_status);
+		return False;
+	}
+
+	gss_test_oid_set_member(&minor_status, mech, mech_set, &mech_found);
+
+	if (GSS_ERROR(major_status))
+	{
+		cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to match mechanism in set",
+				      major_status, minor_status);
+		return False;
+	}
+
+	if (!mech_found)
+		return False;
+
+	return True;
+}
+
+static RD_BOOL
+cssp_gss_get_service_name(char *server, gss_name_t * name)
+{
+	gss_buffer_desc output;
+	OM_uint32 major_status, minor_status;
+
+	const char service_name[] = "TERMSRV";
+
+	gss_OID type = (gss_OID) GSS_C_NT_HOSTBASED_SERVICE;
+	int size = (strlen(service_name) + 1 + strlen(server) + 1);
+
+	output.value = malloc(size);
+	snprintf(output.value, size, "%s@%s", service_name, server);
+	output.length = strlen(output.value) + 1;
+
+	major_status = gss_import_name(&minor_status, &output, type, name);
+
+	if (GSS_ERROR(major_status))
+	{
+		cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to create service principal name",
+				      major_status, minor_status);
+		return False;
+	}
+
+	gss_release_buffer(&minor_status, &output);
+
+	return True;
+
+}
+
+static RD_BOOL
+cssp_gss_wrap(gss_ctx_id_t * ctx, STREAM in, STREAM out)
+{
+	int conf_state;
+	OM_uint32 major_status;
+	OM_uint32 minor_status;
+	gss_buffer_desc inbuf, outbuf;
+
+	inbuf.value = in->data;
+	inbuf.length = s_length(in);
+
+	major_status = gss_wrap(&minor_status, ctx, True,
+				GSS_C_QOP_DEFAULT, &inbuf, &conf_state, &outbuf);
+
+	if (major_status != GSS_S_COMPLETE)
+	{
+		cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to encrypt and sign message",
+				      major_status, minor_status);
+		return False;
+	}
+
+	if (!conf_state)
+	{
+		error("GSS Confidentiality failed, no encryption of message performed.");
+		return False;
+	}
+
+	// write enc data to out stream
+	out->data = out->p = xmalloc(outbuf.length);
+	out->size = outbuf.length;
+	out_uint8p(out, outbuf.value, outbuf.length);
+	s_mark_end(out);
+
+	gss_release_buffer(&minor_status, &outbuf);
+
+	return True;
+}
+
+static RD_BOOL
+cssp_gss_unwrap(gss_ctx_id_t * ctx, STREAM in, STREAM out)
+{
+	OM_uint32 major_status;
+	OM_uint32 minor_status;
+	gss_qop_t qop_state;
+	gss_buffer_desc inbuf, outbuf;
+	int conf_state;
+
+	inbuf.value = in->data;
+	inbuf.length = s_length(in);
+
+	major_status = gss_unwrap(&minor_status, ctx, &inbuf, &outbuf, &conf_state, &qop_state);
+
+	if (major_status != GSS_S_COMPLETE)
+	{
+		cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to decrypt message",
+				      major_status, minor_status);
+		return False;
+	}
+
+	out->data = out->p = xmalloc(outbuf.length);
+	out->size = outbuf.length;
+	out_uint8p(out, outbuf.value, outbuf.length);
+	s_mark_end(out);
+
+	gss_release_buffer(&minor_status, &outbuf);
+
+	return True;
+}
+
+#ifdef WITH_DEBUG_CREDSSP
+void
+streamsave(STREAM s, char *fn)
+{
+	FILE *f = fopen(fn, "wb");
+	fwrite(s->data, s_length(s), 1, f);
+	fclose(f);
+}
+#endif
+
+static STREAM
+cssp_encode_tspasswordcreds(char *username, char *password, char *domain)
+{
+	STREAM out, h1, h2;
+	struct stream tmp = { 0 };
+	struct stream message = { 0 };
+
+	memset(&tmp, 0, sizeof(tmp));
+	memset(&message, 0, sizeof(message));
+
+	// domainName [0]
+	s_realloc(&tmp, 4 + strlen(domain) * sizeof(uint16));
+	s_reset(&tmp);
+	rdp_out_unistr(&tmp, domain, strlen(domain) * sizeof(uint16));
+	s_mark_end(&tmp);
+	h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
+	h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
+	s_realloc(&message, s_length(&message) + s_length(h1));
+	out_uint8p(&message, h1->data, s_length(h1));
+	s_mark_end(&message);
+	s_free(h2);
+	s_free(h1);
+
+	// userName [1]
+	s_realloc(&tmp, 4 + strlen(username) * sizeof(uint16));
+	s_reset(&tmp);
+	rdp_out_unistr(&tmp, username, strlen(username) * sizeof(uint16));
+	s_mark_end(&tmp);
+
+	h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
+	h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
+	s_realloc(&message, s_length(&message) + s_length(h1));
+	out_uint8p(&message, h1->data, s_length(h1));
+	s_mark_end(&message);
+	s_free(h2);
+	s_free(h1);
+
+	// password [2]
+	s_realloc(&tmp, 4 + strlen(password) * sizeof(uint16));
+	s_reset(&tmp);
+	rdp_out_unistr(&tmp, password, strlen(password) * sizeof(uint16));
+	s_mark_end(&tmp);
+	h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
+	h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
+	s_realloc(&message, s_length(&message) + s_length(h1));
+	out_uint8p(&message, h1->data, s_length(h1));
+	s_mark_end(&message);
+	s_free(h2);
+	s_free(h1);
+
+	// build message
+	out = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message);
+
+	// cleanup
+	xfree(tmp.data);
+	xfree(message.data);
+	return out;
+}
+
+/* KeySpecs from wincrypt.h */
+#define AT_KEYEXCHANGE 1
+#define AT_SIGNATURE   2
+
+static STREAM
+cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, char *container,
+			    char *csp)
+{
+	STREAM out;
+	STREAM h1, h2;
+	struct stream tmp = { 0 };
+	struct stream message = { 0 };
+
+	// keySpec [0]
+	s_realloc(&tmp, sizeof(uint8));
+	s_reset(&tmp);
+	out_uint8(&tmp, keyspec);
+	s_mark_end(&tmp);
+	h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
+	h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
+	s_realloc(&message, s_length(&message) + s_length(h1));
+	out_uint8p(&message, h1->data, s_length(h1));
+	s_mark_end(&message);
+	s_free(h2);
+	s_free(h1);
+
+	// cardName [1]
+	if (card)
+	{
+		s_realloc(&tmp, 4 + strlen(card) * sizeof(uint16));
+		s_reset(&tmp);
+		rdp_out_unistr(&tmp, card, strlen(card) * sizeof(uint16));
+		s_mark_end(&tmp);
+		h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
+		h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
+		s_realloc(&message, s_length(&message) + s_length(h1));
+		out_uint8p(&message, h1->data, s_length(h1));
+		s_mark_end(&message);
+		s_free(h2);
+		s_free(h1);
+	}
+
+	// readerName [2]
+	if (reader)
+	{
+		s_realloc(&tmp, 4 + strlen(reader) * sizeof(uint16));
+		s_reset(&tmp);
+		rdp_out_unistr(&tmp, reader, strlen(reader) * sizeof(uint16));
+		s_mark_end(&tmp);
+		h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
+		h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
+		s_realloc(&message, s_length(&message) + s_length(h1));
+		out_uint8p(&message, h1->data, s_length(h1));
+		s_mark_end(&message);
+		s_free(h2);
+		s_free(h1);
+	}
+
+	// containerName [3]
+	if (container)
+	{
+		s_realloc(&tmp, 4 + strlen(container) * sizeof(uint16));
+		s_reset(&tmp);
+		rdp_out_unistr(&tmp, container, strlen(container) * sizeof(uint16));
+		s_mark_end(&tmp);
+		h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
+		h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
+		s_realloc(&message, s_length(&message) + s_length(h1));
+		out_uint8p(&message, h1->data, s_length(h1));
+		s_mark_end(&message);
+		s_free(h2);
+		s_free(h1);
+	}
+
+	// cspName [4]
+	if (csp)
+	{
+		s_realloc(&tmp, 4 + strlen(csp) * sizeof(uint16));
+		s_reset(&tmp);
+		rdp_out_unistr(&tmp, csp, strlen(csp) * sizeof(uint16));
+		s_mark_end(&tmp);
+		h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
+		h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 4, h2);
+		s_realloc(&message, s_length(&message) + s_length(h1));
+		out_uint8p(&message, h1->data, s_length(h1));
+		s_mark_end(&message);
+		s_free(h2);
+		s_free(h1);
+	}
+
+	s_mark_end(&message);
+
+	// build message
+	out = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message);
+
+	// cleanup
+	free(tmp.data);
+	free(message.data);
+	return out;
+}
+
+static STREAM
+cssp_encode_tssmartcardcreds(char *username, char *password, char *domain)
+{
+	STREAM out, h1, h2;
+	struct stream tmp = { 0 };
+	struct stream message = { 0 };
+
+	// pin [0]
+	s_realloc(&tmp, strlen(password) * sizeof(uint16));
+	s_reset(&tmp);
+	rdp_out_unistr(&tmp, password, strlen(password) * sizeof(uint16));
+	s_mark_end(&tmp);
+	h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
+	h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
+	s_realloc(&message, s_length(&message) + s_length(h1));
+	out_uint8p(&message, h1->data, s_length(h1));
+	s_mark_end(&message);
+	s_free(h2);
+	s_free(h1);
+
+	// cspData[1]        
+	h2 = cssp_encode_tscspdatadetail(AT_KEYEXCHANGE, g_sc_card_name, g_sc_reader_name,
+					 g_sc_container_name, g_sc_csp_name);
+	h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
+	s_realloc(&message, s_length(&message) + s_length(h1));
+	out_uint8p(&message, h1->data, s_length(h1));
+	s_mark_end(&message);
+	s_free(h2);
+	s_free(h1);
+
+	// userHint [2]
+	if (username && strlen(username))
+	{
+		s_realloc(&tmp, strlen(username) * sizeof(uint16));
+		s_reset(&tmp);
+		rdp_out_unistr(&tmp, username, strlen(username) * sizeof(uint16));
+		s_mark_end(&tmp);
+		h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
+		h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
+		s_realloc(&message, s_length(&message) + s_length(h1));
+		out_uint8p(&message, h1->data, s_length(h1));
+		s_mark_end(&message);
+		s_free(h2);
+		s_free(h1);
+	}
+
+	// domainHint [3]
+	if (domain && strlen(domain))
+	{
+		s_realloc(&tmp, strlen(domain) * sizeof(uint16));
+		s_reset(&tmp);
+		rdp_out_unistr(&tmp, domain, strlen(domain) * sizeof(uint16));
+		s_mark_end(&tmp);
+		h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
+		h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
+		s_realloc(&message, s_length(&message) + s_length(h1));
+		out_uint8p(&message, h1->data, s_length(h1));
+		s_mark_end(&message);
+		s_free(h2);
+		s_free(h1);
+	}
+
+	s_mark_end(&message);
+
+	// build message
+	out = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message);
+
+	// cleanup
+	free(tmp.data);
+	free(message.data);
+	return out;
+}
+
+STREAM
+cssp_encode_tscredentials(char *username, char *password, char *domain)
+{
+	STREAM out;
+	STREAM h1, h2, h3;
+	struct stream tmp = { 0 };
+	struct stream message = { 0 };
+
+	// credType [0]
+	s_realloc(&tmp, sizeof(uint8));
+	s_reset(&tmp);
+	if (g_use_password_as_pin == False)
+	{
+		out_uint8(&tmp, 1);	// TSPasswordCreds
+	}
+	else
+	{
+		out_uint8(&tmp, 2);	// TSSmartCardCreds
+	}
+
+	s_mark_end(&tmp);
+	h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
+	h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
+	s_realloc(&message, s_length(&message) + s_length(h1));
+	out_uint8p(&message, h1->data, s_length(h1));
+	s_mark_end(&message);
+	s_free(h2);
+	s_free(h1);
+
+	// credentials [1]
+	if (g_use_password_as_pin == False)
+	{
+		h3 = cssp_encode_tspasswordcreds(username, password, domain);
+	}
+	else
+	{
+		h3 = cssp_encode_tssmartcardcreds(username, password, domain);
+	}
+
+	h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, h3);
+	h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
+	s_realloc(&message, s_length(&message) + s_length(h1));
+	out_uint8p(&message, h1->data, s_length(h1));
+	s_mark_end(&message);
+	s_free(h3);
+	s_free(h2);
+	s_free(h1);
+
+	// Construct ASN.1 message
+	out = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message);
+
+#if WITH_DEBUG_CREDSSP
+	streamsave(out, "tscredentials.raw");
+	printf("Out TSCredentials %ld bytes\n", s_length(out));
+	hexdump(out->data, s_length(out));
+#endif
+
+	// cleanup
+	xfree(message.data);
+	xfree(tmp.data);
+
+	return out;
+}
+
+RD_BOOL
+cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey)
+{
+	STREAM s;
+	STREAM h1, h2, h3, h4, h5;
+
+	struct stream tmp = { 0 };
+	struct stream message = { 0 };
+
+	memset(&message, 0, sizeof(message));
+	memset(&tmp, 0, sizeof(tmp));
+
+	// version [0]
+	s_realloc(&tmp, sizeof(uint8));
+	s_reset(&tmp);
+	out_uint8(&tmp, 2);
+	s_mark_end(&tmp);
+	h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
+	h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
+	s_realloc(&message, s_length(&message) + s_length(h1));
+	out_uint8p(&message, h1->data, s_length(h1));
+	s_mark_end(&message);
+	s_free(h2);
+	s_free(h1);
+
+	// negoToken [1]
+	if (token && s_length(token))
+	{
+		h5 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, token);
+		h4 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h5);
+		h3 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, h4);
+		h2 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, h3);
+		h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
+		s_realloc(&message, s_length(&message) + s_length(h1));
+		out_uint8p(&message, h1->data, s_length(h1));
+		s_mark_end(&message);
+		s_free(h5);
+		s_free(h4);
+		s_free(h3);
+		s_free(h2);
+		s_free(h1);
+	}
+
+	// authInfo [2]
+	if (auth && s_length(auth))
+	{
+		h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, auth);
+		h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
+
+		s_realloc(&message, s_length(&message) + s_length(h1));
+		out_uint8p(&message, h1->data, s_length(h1));
+
+		s_free(h2);
+		s_free(h1);
+	}
+
+	// pubKeyAuth [3]
+	if (pubkey && s_length(pubkey))
+	{
+		h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, pubkey);
+		h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
+
+		s_realloc(&message, s_length(&message) + s_length(h1));
+		out_uint8p(&message, h1->data, s_length(h1));
+		s_mark_end(&message);
+		s_free(h2);
+		s_free(h1);
+	}
+	s_mark_end(&message);
+
+	// Construct ASN.1 Message
+	// Todo: can h1 be send directly instead of tcp_init() approach
+	h1 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message);
+	s = tcp_init(s_length(h1));
+	out_uint8p(s, h1->data, s_length(h1));
+	s_mark_end(s);
+	s_free(h1);
+
+#if WITH_DEBUG_CREDSSP
+	streamsave(s, "tsrequest_out.raw");
+	printf("Out TSRequest %ld bytes\n", s_length(s));
+	hexdump(s->data, s_length(s));
+#endif
+
+	tcp_send(s);
+
+	// cleanup
+	xfree(message.data);
+	xfree(tmp.data);
+
+	return True;
+}
+
+
+RD_BOOL
+cssp_read_tsrequest(STREAM token, STREAM pubkey)
+{
+	STREAM s;
+	int length;
+	int tagval;
+
+	s = tcp_recv(NULL, 4);
+
+	if (s == NULL)
+		return False;
+
+	// verify ASN.1 header
+	if (s->p[0] != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
+	{
+		error("Expected BER_TAG_SEQUENCE|BER_TAG_CONSTRUCTED, got %x", s->p[0]);
+		return False;
+	}
+
+	// peek at first 4 bytes to get full message length
+	if (s->p[1] < 0x80)
+		length = s->p[1] - 2;
+	else if (s->p[1] == 0x81)
+		length = s->p[2] - 1;
+	else if (s->p[1] == 0x82)
+		length = (s->p[2] << 8) | s->p[3];
+	else
+		return False;
+
+	// receive the remainings of message
+	s = tcp_recv(s, length);
+
+#if WITH_DEBUG_CREDSSP
+	streamsave(s, "tsrequest_in.raw");
+	printf("In TSRequest token %ld bytes\n", s_length(s));
+	hexdump(s->data, s_length(s));
+#endif
+
+	// parse the response and into nego token
+	if (!ber_in_header(s, &tagval, &length) ||
+	    tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
+		return False;
+
+	// version [0]
+	if (!ber_in_header(s, &tagval, &length) ||
+	    tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
+		return False;
+	in_uint8s(s, length);
+
+	// negoToken [1]
+	if (token)
+	{
+		if (!ber_in_header(s, &tagval, &length)
+		    || tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1))
+			return False;
+		if (!ber_in_header(s, &tagval, &length)
+		    || tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
+			return False;
+		if (!ber_in_header(s, &tagval, &length)
+		    || tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
+			return False;
+		if (!ber_in_header(s, &tagval, &length)
+		    || tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
+			return False;
+
+		if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING)
+			return False;
+
+		token->end = token->p = token->data;
+		out_uint8p(token, s->p, length);
+		s_mark_end(token);
+	}
+
+	// pubKey [3]
+	if (pubkey)
+	{
+		if (!ber_in_header(s, &tagval, &length)
+		    || tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3))
+			return False;
+
+		if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING)
+			return False;
+
+		pubkey->data = pubkey->p = s->p;
+		pubkey->end = pubkey->data + length;
+		pubkey->size = length;
+	}
+
+
+	return True;
+}
+
+RD_BOOL
+cssp_connect(char *server, char *user, char *domain, char *password, STREAM s)
+{
+	OM_uint32 actual_time;
+	gss_cred_id_t cred;
+	gss_buffer_desc input_tok, output_tok;
+	gss_name_t target_name;
+	OM_uint32 major_status, minor_status;
+	int context_established = 0;
+	gss_ctx_id_t gss_ctx;
+	gss_OID desired_mech = &_gss_spnego_krb5_mechanism_oid_desc;
+
+	STREAM ts_creds;
+	struct stream token = { 0 };
+	struct stream pubkey = { 0 };
+	struct stream pubkey_cmp = { 0 };
+
+	// Verify that system gss support spnego
+	if (!cssp_gss_mech_available(desired_mech))
+	{
+		warning("CredSSP: System doesn't have support for desired authentication mechanism.\n");
+		return False;
+	}
+
+	// Get service name
+	if (!cssp_gss_get_service_name(server, &target_name))
+	{
+		warning("CredSSP: Failed to get target service name.\n");
+		return False;
+	}
+
+	// Establish tls connection to server
+	if (!tcp_tls_connect())
+	{
+		warning("CredSSP: Failed to establish TLS connection.\n");
+		return False;
+	}
+
+	tcp_tls_get_server_pubkey(&pubkey);
+
+#ifdef WITH_DEBUG_CREDSSP
+	streamsave(&pubkey, "PubKey.raw");
+#endif
+
+	// Enter the spnego loop
+	OM_uint32 actual_services;
+	gss_OID actual_mech;
+	struct stream blob = { 0 };
+
+	gss_ctx = GSS_C_NO_CONTEXT;
+	cred = GSS_C_NO_CREDENTIAL;
+
+	input_tok.length = 0;
+	output_tok.length = 0;
+	minor_status = 0;
+
+	int i = 0;
+
+	do
+	{
+		major_status = gss_init_sec_context(&minor_status,
+						    cred,
+						    &gss_ctx,
+						    target_name,
+						    desired_mech,
+						    GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG,
+						    GSS_C_INDEFINITE,
+						    GSS_C_NO_CHANNEL_BINDINGS,
+						    &input_tok,
+						    &actual_mech,
+						    &output_tok, &actual_services, &actual_time);
+
+		if (GSS_ERROR(major_status))
+		{
+			if (i == 0)
+				error("CredSSP: Initialize failed, do you have correct kerberos tgt initialized ?\n");
+			else
+				error("CredSSP: Negotiation failed.\n");
+
+#ifdef WITH_DEBUG_CREDSSP
+			cssp_gss_report_error(GSS_C_GSS_CODE, "CredSSP: SPNEGO negotiation failed.",
+					      major_status, minor_status);
+#endif
+			goto bail_out;
+		}
+
+		// validate required services
+		if (!(actual_services & GSS_C_CONF_FLAG))
+		{
+			error("CredSSP: Confidiality service required but is not available.\n");
+			goto bail_out;
+		}
+
+		// Send token to server
+		if (output_tok.length != 0)
+		{
+			if (output_tok.length > token.size)
+				s_realloc(&token, output_tok.length);
+			s_reset(&token);
+
+			out_uint8p(&token, output_tok.value, output_tok.length);
+			s_mark_end(&token);
+
+			if (!cssp_send_tsrequest(&token, NULL, NULL))
+				goto bail_out;
+
+			(void) gss_release_buffer(&minor_status, &output_tok);
+		}
+
+		// Read token from server
+		if (major_status & GSS_S_CONTINUE_NEEDED)
+		{
+			(void) gss_release_buffer(&minor_status, &input_tok);
+
+			if (!cssp_read_tsrequest(&token, NULL))
+				goto bail_out;
+
+			input_tok.value = token.data;
+			input_tok.length = s_length(&token);
+		}
+		else
+		{
+			// Send encrypted pubkey for verification to server
+			context_established = 1;
+
+			if (!cssp_gss_wrap(gss_ctx, &pubkey, &blob))
+				goto bail_out;
+
+			if (!cssp_send_tsrequest(NULL, NULL, &blob))
+				goto bail_out;
+
+			context_established = 1;
+		}
+
+		i++;
+
+	}
+	while (!context_established);
+
+	// read tsrequest response and decrypt for public key validation
+	if (!cssp_read_tsrequest(NULL, &blob))
+		goto bail_out;
+
+	if (!cssp_gss_unwrap(gss_ctx, &blob, &pubkey_cmp))
+		goto bail_out;
+
+	pubkey_cmp.data[0] -= 1;
+
+	// validate public key
+	if (memcmp(pubkey.data, pubkey_cmp.data, s_length(&pubkey)) != 0)
+	{
+		error("CredSSP: Cannot guarantee integrity of server connection, MITM ? "
+		      "(public key data mismatch)\n");
+		goto bail_out;
+	}
+
+	// Send TSCredentials
+	ts_creds = cssp_encode_tscredentials(user, password, domain);
+
+	if (!cssp_gss_wrap(gss_ctx, ts_creds, &blob))
+		goto bail_out;
+
+	s_free(ts_creds);
+
+	if (!cssp_send_tsrequest(NULL, &blob, NULL))
+		goto bail_out;
+
+	return True;
+
+      bail_out:
+	xfree(token.data);
+	return False;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/ctrl.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/ctrl.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/ctrl.c	(revision 55121)
@@ -0,0 +1,518 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Master/Slave remote controlling
+   Copyright 2013 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "rdesktop.h"
+#include "ssl.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <limits.h>
+#include <unistd.h>
+
+#define CTRL_LINEBUF_SIZE 1024
+#define CTRL_RESULT_SIZE 32
+#define RDESKTOP_CTRLSOCK_STORE "/.local/share/rdesktop/ctrl"
+
+#define CTRL_HASH_FLAG_SEAMLESS  1
+
+#define ERR_RESULT_OK 0x00
+#define ERR_RESULT_NO_SUCH_COMMAND 0xffffffff
+
+extern RD_BOOL g_seamless_rdp;
+extern uint8 g_static_rdesktop_salt_16[];
+
+static RD_BOOL _ctrl_is_slave;
+static int ctrlsock;
+static char ctrlsock_name[PATH_MAX];
+static struct _ctrl_slave_t *_ctrl_slaves;
+
+#define CMD_SEAMLESS_SPAWN "seamless.spawn"
+
+typedef struct _ctrl_slave_t
+{
+	struct _ctrl_slave_t *prev, *next;
+	int sock;
+	char linebuf[CTRL_LINEBUF_SIZE];
+} _ctrl_slave_t;
+
+
+static void
+_ctrl_slave_new(int sock)
+{
+	_ctrl_slave_t *it, *ns;
+
+	/* initialize new slave list item */
+	ns = (_ctrl_slave_t *) xmalloc(sizeof(_ctrl_slave_t));
+	memset(ns, 0, sizeof(_ctrl_slave_t));
+	ns->sock = sock;
+
+	/* append new slave to end of list */
+	it = _ctrl_slaves;
+
+	/* find last element in list */
+	while (it && it->next)
+		it = it->next;
+
+	/* if last found append new */
+	if (it)
+	{
+		it->next = ns;
+		ns->prev = it;
+	}
+	else
+	{
+		/* no elemnts in list, lets add first */
+		_ctrl_slaves = ns;
+	}
+}
+
+static void
+_ctrl_slave_disconnect(int sock)
+{
+	_ctrl_slave_t *it;
+
+	if (!_ctrl_slaves)
+		return;
+
+	it = _ctrl_slaves;
+
+	/* find slave with sock */
+	while (it->next && it->sock != sock)
+		it = it->next;
+
+	if (it->sock == sock)
+	{
+		/* shutdown socket */
+		shutdown(sock, SHUT_RDWR);
+		close(sock);
+
+		/* remove item from list */
+		if (it == _ctrl_slaves)
+		{
+			if (it->next)
+				_ctrl_slaves = it->next;
+			else
+				_ctrl_slaves = NULL;
+		}
+
+		if (it->prev)
+		{
+			(it->prev)->next = it->next;
+			if (it->next)
+				(it->next)->prev = it->prev;
+		}
+		else if (it->next)
+			(it->next)->prev = NULL;
+
+		xfree(it);
+
+	}
+}
+
+static void
+_ctrl_command_result(_ctrl_slave_t * slave, int result)
+{
+	char buf[64] = { 0 };
+
+	/* translate and send result code back to client */
+	if (result == 0)
+		send(slave->sock, "OK\n", 3, 0);
+	else
+	{
+		snprintf(buf, 64, "ERROR %x\n", result);
+		send(slave->sock, buf, strlen(buf), 0);
+	}
+}
+
+static void
+_ctrl_dispatch_command(_ctrl_slave_t * slave)
+{
+	char *p;
+	char *cmd;
+	unsigned int res;
+
+	/* unescape linebuffer */
+	cmd = utils_string_unescape(slave->linebuf);
+	if (strncmp(cmd, CMD_SEAMLESS_SPAWN " ", strlen(CMD_SEAMLESS_SPAWN) + 1) == 0)
+	{
+		/* process seamless spawn request */
+		p = strstr(cmd, "seamlessrdpshell.exe");
+		if (p)
+			p += strlen("seamlessrdpshell.exe") + 1;
+		else
+			p = cmd + strlen(CMD_SEAMLESS_SPAWN) + 1;
+
+		res = ERR_RESULT_OK;
+
+		if (seamless_send_spawn(p) == (unsigned int) -1)
+			res = 1;
+	}
+	else
+	{
+		res = ERR_RESULT_NO_SUCH_COMMAND;
+	}
+	xfree(cmd);
+
+	_ctrl_command_result(slave, res);
+}
+
+static RD_BOOL
+_ctrl_verify_unix_socket()
+{
+	int s, len;
+	struct sockaddr_un saun;
+
+	memset(&saun, 0, sizeof(struct sockaddr_un));
+
+	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+	{
+		perror("Error creating ctrl client socket: socket()");
+		exit(1);
+	}
+
+	saun.sun_family = AF_UNIX;
+	strcpy(saun.sun_path, ctrlsock_name);
+	len = sizeof(saun.sun_family) + strlen(saun.sun_path);
+
+	/* test connection */
+	if (connect(s, (struct sockaddr *) &saun, len) != 0)
+		return False;
+
+	shutdown(s, SHUT_RDWR);
+	close(s);
+	return True;
+}
+
+
+static void
+_ctrl_create_hash(const char *user, const char *domain, const char *host, char *hash, size_t hsize)
+{
+	RDSSL_SHA1 sha1;
+	uint8 out[20], delim;
+	uint16 version;
+	uint32 flags;
+
+	/* version\0user\0domain\0host\0flags */
+	flags = 0;
+	delim = '\0';
+	version = 0x0100;
+
+	if (g_seamless_rdp)
+		flags = CTRL_HASH_FLAG_SEAMLESS;
+
+	rdssl_sha1_init(&sha1);
+	rdssl_sha1_update(&sha1, (uint8 *) & version, sizeof(version));
+	rdssl_sha1_update(&sha1, &delim, 1);
+
+	if (user)
+		rdssl_sha1_update(&sha1, (uint8 *) user, strlen(user));
+	rdssl_sha1_update(&sha1, &delim, 1);
+
+	if (domain)
+		rdssl_sha1_update(&sha1, (uint8 *) domain, strlen(domain));
+	rdssl_sha1_update(&sha1, &delim, 1);
+
+	if (host)
+		rdssl_sha1_update(&sha1, (uint8 *) host, strlen(host));
+	rdssl_sha1_update(&sha1, &delim, 1);
+
+	rdssl_sha1_update(&sha1, (uint8 *) & flags, sizeof(flags));
+	rdssl_sha1_final(&sha1, out);
+
+	sec_hash_to_string(hash, hsize, out, sizeof(out));
+}
+
+
+/** Initialize ctrl
+    Ret values: <0 failure, 0 master, 1 client
+ */
+int
+ctrl_init(const char *user, const char *domain, const char *host)
+{
+	struct stat st;
+	struct sockaddr_un saun;
+	char hash[41], path[PATH_MAX];
+	char *home;
+
+	/* check if ctrl already initialized */
+	if (ctrlsock != 0 || _ctrl_is_slave)
+		return 0;
+
+	home = getenv("HOME");
+	if (home == NULL)
+	{
+		return -1;
+	}
+
+	/* get uniq hash for ctrlsock name */
+	_ctrl_create_hash(user, domain, host, hash, 41);
+	snprintf(ctrlsock_name, PATH_MAX, "%s" RDESKTOP_CTRLSOCK_STORE "/%s.ctl", home, hash);
+	ctrlsock_name[sizeof(ctrlsock_name) - 1] = '\0';
+
+	/* make sure that ctrlsock store path exists */
+	snprintf(path, PATH_MAX, "%s" RDESKTOP_CTRLSOCK_STORE, home);
+	path[sizeof(path) - 1] = '\0';
+	if (utils_mkdir_p(path, 0700) == -1)
+	{
+		perror(path);
+		return -1;
+	}
+
+	/* check if ctrl socket already exist then this process becomes a client */
+	if (stat(ctrlsock_name, &st) == 0)
+	{
+		/* verify that unix socket is not stale */
+		if (_ctrl_verify_unix_socket() == True)
+		{
+			_ctrl_is_slave = True;
+			return 1;
+		}
+		else
+		{
+			unlink(ctrlsock_name);
+		}
+	}
+
+	/* setup ctrl socket and start listening for connections */
+	if ((ctrlsock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+	{
+		perror("Error creating ctrl socket:");
+		exit(1);
+	}
+
+	/* bind and start listening on server socket */
+	memset(&saun, 0, sizeof(struct sockaddr_un));
+	saun.sun_family = AF_UNIX;
+	strncpy(saun.sun_path, ctrlsock_name, sizeof(saun.sun_path));
+	if (bind(ctrlsock, (struct sockaddr *) &saun, sizeof(struct sockaddr_un)) < 0)
+	{
+		perror("Error binding ctrl socket:");
+		exit(1);
+	}
+
+	if (listen(ctrlsock, 5) < 0)
+	{
+		perror("Error listening on socket:");
+		exit(1);
+	}
+
+	/* add ctrl cleanup func to exit hooks */
+	atexit(ctrl_cleanup);
+
+	return 0;
+}
+
+void
+ctrl_cleanup()
+{
+	if (ctrlsock)
+	{
+		close(ctrlsock);
+		unlink(ctrlsock_name);
+	}
+}
+
+RD_BOOL
+ctrl_is_slave()
+{
+	return _ctrl_is_slave;
+}
+
+
+void
+ctrl_add_fds(int *n, fd_set * rfds)
+{
+	_ctrl_slave_t *it;
+	if (ctrlsock == 0)
+		return;
+
+	FD_SET(ctrlsock, rfds);
+	*n = MAX(*n, ctrlsock);
+
+
+	/* add connected slaves to fd set */
+	it = _ctrl_slaves;
+	while (it)
+	{
+		FD_SET(it->sock, rfds);
+		*n = MAX(*n, it->sock);
+		it = it->next;
+	}
+}
+
+void
+ctrl_check_fds(fd_set * rfds, fd_set * wfds)
+{
+	int ns, res, offs;
+	struct sockaddr_un fsaun;
+	socklen_t fromlen;
+	_ctrl_slave_t *it;
+
+	if (ctrlsock == 0)
+		return;
+
+	memset(&fsaun, 0, sizeof(struct sockaddr_un));
+
+	/* check if we got any connections on server socket */
+	if (FD_ISSET(ctrlsock, rfds))
+	{
+		FD_CLR(ctrlsock, rfds);
+		fromlen = sizeof(fsaun);
+		ns = accept(ctrlsock, (struct sockaddr *) &fsaun, &fromlen);
+		if (ns < 0)
+		{
+			perror("server: accept()");
+			exit(1);
+		}
+
+		_ctrl_slave_new(ns);
+		return;
+	}
+
+	/* check if any of our slaves fds has data */
+	it = _ctrl_slaves;
+	while (it)
+	{
+		if (FD_ISSET(it->sock, rfds))
+		{
+			offs = strlen(it->linebuf);
+			res = recv(it->sock, it->linebuf + offs, CTRL_LINEBUF_SIZE - offs, 0);
+			FD_CLR(it->sock, rfds);
+
+			/* linebuffer full let's disconnect slave */
+			if (it->linebuf[CTRL_LINEBUF_SIZE - 1] != '\0' &&
+			    it->linebuf[CTRL_LINEBUF_SIZE - 1] != '\n')
+			{
+				_ctrl_slave_disconnect(it->sock);
+				break;
+			}
+
+			if (res > 0)
+			{
+				/* Check if we got full command line */
+				char *p;
+				if ((p = strchr(it->linebuf, '\n')) == NULL)
+					continue;
+
+				/* iterate over string and check against escaped \n */
+				while (p)
+				{
+					/* Check if newline is escaped */
+					if (p > it->linebuf && *(p - 1) != '\\')
+						break;
+					p = strchr(p + 1, '\n');
+				}
+
+				/* If we havent found an nonescaped \n we need more data */
+				if (p == NULL)
+					continue;
+
+				/* strip new linebuf and dispatch command */
+				*p = '\0';
+				_ctrl_dispatch_command(it);
+				memset(it->linebuf, 0, CTRL_LINEBUF_SIZE);
+			}
+			else
+			{
+				/* Peer disconnected or socket error */
+				_ctrl_slave_disconnect(it->sock);
+				break;
+			}
+		}
+		it = it->next;
+	}
+}
+
+#if HAVE_ICONV
+extern char g_codepage[16];
+#endif
+
+int
+ctrl_send_command(const char *cmd, const char *arg)
+{
+	FILE *fp;
+	struct sockaddr_un saun;
+	int s, len, index, ret;
+	char data[CTRL_LINEBUF_SIZE], tmp[CTRL_LINEBUF_SIZE];
+	char result[CTRL_RESULT_SIZE], c, *escaped;
+
+	escaped = NULL;
+
+	if (!_ctrl_is_slave)
+		return -1;
+
+	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+	{
+		perror("Error creating ctrl client socket: socket()");
+		exit(1);
+	}
+
+	memset(&saun, 0, sizeof(struct sockaddr_un));
+	saun.sun_family = AF_UNIX;
+	strcpy(saun.sun_path, ctrlsock_name);
+	len = sizeof(saun.sun_family) + strlen(saun.sun_path);
+
+	if (connect(s, (struct sockaddr *) &saun, len) < 0)
+	{
+		perror("Error connecting to ctrl socket: connect()");
+		exit(1);
+	}
+
+	/* Bundle cmd and argument into string, convert to UTF-8 if needed */
+	snprintf(data, CTRL_LINEBUF_SIZE, "%s %s", cmd, arg);
+	ret = utils_locale_to_utf8(data, strlen(data), tmp, CTRL_LINEBUF_SIZE - 1);
+
+	if (ret != 0)
+		goto bail_out;
+
+	/* escape the utf-8 string */
+	escaped = utils_string_escape(tmp);
+	if ((strlen(escaped) + 1) > CTRL_LINEBUF_SIZE - 1)
+		goto bail_out;
+
+	/* send escaped utf-8 command to master */
+	send(s, escaped, strlen(escaped), 0);
+	send(s, "\n", 1, 0);
+
+	/* read result from master */
+	fp = fdopen(s, "r");
+	index = 0;
+	while ((c = fgetc(fp)) != EOF && index < CTRL_RESULT_SIZE && c != '\n')
+	{
+		result[index] = c;
+		index++;
+	}
+	result[index - 1] = '\0';
+
+	if (strncmp(result, "ERROR ", 6) == 0)
+	{
+		if (sscanf(result, "ERROR %d", &ret) != 1)
+			ret = -1;
+	}
+
+      bail_out:
+	xfree(escaped);
+	shutdown(s, SHUT_RDWR);
+	close(s);
+
+	return ret;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/disk.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/disk.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/disk.c	(revision 55121)
@@ -0,0 +1,1399 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Disk Redirection
+   Copyright (C) Jeroen Meijer <jeroen@oldambt7.com> 2003-2008
+   Copyright 2003-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "disk.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>		/* open, close */
+#include <dirent.h>		/* opendir, closedir, readdir */
+#include <fnmatch.h>
+#include <errno.h>		/* errno */
+#include <stdio.h>
+
+#include <utime.h>
+#include <time.h>		/* ctime */
+
+#if (defined(HAVE_DIRFD) || (HAVE_DECL_DIRFD == 1))
+#define DIRFD(a) (dirfd(a))
+#else
+#define DIRFD(a) ((a)->DIR_FD_MEMBER_NAME)
+#endif
+
+/* TODO: Fix mntent-handling for solaris
+ * #include <sys/mntent.h> */
+#if (defined(HAVE_MNTENT_H) && defined(HAVE_SETMNTENT))
+#include <mntent.h>
+#define MNTENT_PATH "/etc/mtab"
+#define USE_SETMNTENT
+#endif
+
+#ifdef HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#endif
+
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+
+#ifdef HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/mount.h>
+#endif
+
+#include "rdesktop.h"
+
+#ifdef STAT_STATFS3_OSF1
+#define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf)))
+#define STATFS_T statfs
+#define USE_STATFS
+#endif
+
+#ifdef STAT_STATVFS
+#define STATFS_FN(path, buf) (statvfs(path,buf))
+#define STATFS_T statvfs
+#define USE_STATVFS
+#endif
+
+#ifdef STAT_STATVFS64
+#define STATFS_FN(path, buf) (statvfs64(path,buf))
+#define STATFS_T statvfs64
+#define USE_STATVFS
+#endif
+
+#if (defined(STAT_STATFS2_FS_DATA) || defined(STAT_STATFS2_BSIZE) || defined(STAT_STATFS2_FSIZE))
+#define STATFS_FN(path, buf) (statfs(path,buf))
+#define STATFS_T statfs
+#define USE_STATFS
+#endif
+
+#ifdef STAT_STATFS4
+#define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf),0))
+#define STATFS_T statfs
+#define USE_STATFS
+#endif
+
+#if ((defined(USE_STATFS) && defined(HAVE_STRUCT_STATFS_F_NAMEMAX)) || (defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_NAMEMAX)))
+#define F_NAMELEN(buf) ((buf).f_namemax)
+#endif
+
+#if ((defined(USE_STATFS) && defined(HAVE_STRUCT_STATFS_F_NAMELEN)) || (defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_NAMELEN)))
+#define F_NAMELEN(buf) ((buf).f_namelen)
+#endif
+
+#ifndef F_NAMELEN
+#define F_NAMELEN(buf) (255)
+#endif
+
+/* Dummy statfs fallback */
+#ifndef STATFS_T
+struct dummy_statfs_t
+{
+	long f_bfree;
+	long f_bsize;
+	long f_bavail;
+	long f_blocks;
+	int f_namelen;
+	int f_namemax;
+};
+
+static int
+dummy_statfs(struct dummy_statfs_t *buf)
+{
+	buf->f_blocks = 262144;
+	buf->f_bfree = 131072;
+	buf->f_bavail = 131072;
+	buf->f_bsize = 512;
+	buf->f_namelen = 255;
+	buf->f_namemax = 255;
+
+	return 0;
+}
+
+#define STATFS_T dummy_statfs_t
+#define STATFS_FN(path,buf) (dummy_statfs(buf))
+#endif
+
+extern RDPDR_DEVICE g_rdpdr_device[];
+
+FILEINFO g_fileinfo[MAX_OPEN_FILES];
+RD_BOOL g_notify_stamp = False;
+
+typedef struct
+{
+	char name[PATH_MAX];
+	char label[PATH_MAX];
+	unsigned long serial;
+	char type[PATH_MAX];
+} FsInfoType;
+
+static RD_NTSTATUS NotifyInfo(RD_NTHANDLE handle, uint32 info_class, NOTIFY * p);
+
+static time_t
+get_create_time(struct stat *filestat)
+{
+	time_t ret, ret1;
+
+	ret = MIN(filestat->st_ctime, filestat->st_mtime);
+	ret1 = MIN(ret, filestat->st_atime);
+
+	if (ret1 != (time_t) 0)
+		return ret1;
+
+	return ret;
+}
+
+/* Convert seconds since 1970 to a filetime */
+static void
+seconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low)
+{
+	unsigned long long ticks;
+
+	ticks = (seconds + 11644473600LL) * 10000000;
+	*low = (uint32) ticks;
+	*high = (uint32) (ticks >> 32);
+}
+
+/* Convert seconds since 1970 back to filetime */
+static time_t
+convert_1970_to_filetime(uint32 high, uint32 low)
+{
+	unsigned long long ticks;
+	time_t val;
+
+	ticks = low + (((unsigned long long) high) << 32);
+	ticks /= 10000000;
+	ticks -= 11644473600LL;
+
+	val = (time_t) ticks;
+	return (val);
+
+}
+
+/* A wrapper for ftruncate which supports growing files, even if the
+   native ftruncate doesn't. This is needed on Linux FAT filesystems,
+   for example. */
+static int
+ftruncate_growable(int fd, off_t length)
+{
+	int ret;
+	off_t pos;
+	static const char zero = 0;
+
+	/* Try the simple method first */
+	if ((ret = ftruncate(fd, length)) != -1)
+	{
+		return ret;
+	}
+
+	/*
+	 * Some kind of error. Perhaps we were trying to grow. Retry
+	 * in a safe way.
+	 */
+
+	/* Get current position */
+	if ((pos = lseek(fd, 0, SEEK_CUR)) == -1)
+	{
+		perror("lseek");
+		return -1;
+	}
+
+	/* Seek to new size */
+	if (lseek(fd, length, SEEK_SET) == -1)
+	{
+		perror("lseek");
+		return -1;
+	}
+
+	/* Write a zero */
+	if (write(fd, &zero, 1) == -1)
+	{
+		perror("write");
+		return -1;
+	}
+
+	/* Truncate. This shouldn't fail. */
+	if (ftruncate(fd, length) == -1)
+	{
+		perror("ftruncate");
+		return -1;
+	}
+
+	/* Restore position */
+	if (lseek(fd, pos, SEEK_SET) == -1)
+	{
+		perror("lseek");
+		return -1;
+	}
+
+	return 0;
+}
+
+/* Just like open(2), but if a open with O_EXCL fails, retry with
+   GUARDED semantics. This might be necessary because some filesystems
+   (such as NFS filesystems mounted from a unfsd server) doesn't
+   support O_EXCL. GUARDED semantics are subject to race conditions,
+   but we can live with that.
+*/
+static int
+open_weak_exclusive(const char *pathname, int flags, mode_t mode)
+{
+	int ret;
+	struct stat filestat;
+
+	ret = open(pathname, flags, mode);
+	if (ret != -1 || !(flags & O_EXCL))
+	{
+		/* Success, or not using O_EXCL */
+		return ret;
+	}
+
+	/* An error occured, and we are using O_EXCL. In case the FS
+	   doesn't support O_EXCL, some kind of error will be
+	   returned. Unfortunately, we don't know which one. Linux
+	   2.6.8 seems to return 524, but I cannot find a documented
+	   #define for this case. So, we'll return only on errors that
+	   we know aren't related to O_EXCL. */
+	switch (errno)
+	{
+		case EACCES:
+		case EEXIST:
+		case EINTR:
+		case EISDIR:
+		case ELOOP:
+		case ENAMETOOLONG:
+		case ENOENT:
+		case ENOTDIR:
+			return ret;
+	}
+
+	/* Retry with GUARDED semantics */
+	if (stat(pathname, &filestat) != -1)
+	{
+		/* File exists */
+		errno = EEXIST;
+		return -1;
+	}
+	else
+	{
+		return open(pathname, flags & ~O_EXCL, mode);
+	}
+}
+
+/* Enumeration of devices from rdesktop.c        */
+/* returns numer of units found and initialized. */
+/* optarg looks like ':h=/mnt/floppy,b=/mnt/usbdevice1' */
+/* when it arrives to this function.             */
+int
+disk_enum_devices(uint32 * id, char *optarg)
+{
+	char *pos = optarg;
+	char *pos2;
+	int count = 0;
+
+	/* skip the first colon */
+	optarg++;
+	while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
+	{
+		pos2 = next_arg(optarg, '=');
+
+		strncpy(g_rdpdr_device[*id].name, optarg, sizeof(g_rdpdr_device[*id].name) - 1);
+		if (strlen(optarg) > (sizeof(g_rdpdr_device[*id].name) - 1))
+			fprintf(stderr, "share name %s truncated to %s\n", optarg,
+				g_rdpdr_device[*id].name);
+
+		g_rdpdr_device[*id].local_path = (char *) xmalloc(strlen(pos2) + 1);
+		strcpy(g_rdpdr_device[*id].local_path, pos2);
+		g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK;
+		count++;
+		(*id)++;
+
+		optarg = pos;
+	}
+	return count;
+}
+
+/* Opens or creates a file or directory */
+static RD_NTSTATUS
+disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
+	    uint32 flags_and_attributes, char *filename, RD_NTHANDLE * phandle)
+{
+	RD_NTHANDLE handle;
+	DIR *dirp;
+	int flags, mode;
+	char path[PATH_MAX];
+	struct stat filestat;
+
+	handle = 0;
+	dirp = NULL;
+	flags = 0;
+	mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+
+	if (filename && *filename && filename[strlen(filename) - 1] == '/')
+		filename[strlen(filename) - 1] = 0;
+
+	sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename ? filename : "");
+
+	/* Protect against mailicous servers:
+	   somelongpath/..     not allowed
+	   somelongpath/../b   not allowed
+	   somelongpath/..b    in principle ok, but currently not allowed
+	   somelongpath/b..    ok
+	   somelongpath/b..b   ok
+	   somelongpath/b../c  ok
+	 */
+	if (strstr(path, "/.."))
+	{
+		return RD_STATUS_ACCESS_DENIED;
+	}
+
+	switch (create_disposition)
+	{
+		case CREATE_ALWAYS:
+
+			/* Delete existing file/link. */
+			unlink(path);
+			flags |= O_CREAT;
+			break;
+
+		case CREATE_NEW:
+
+			/* If the file already exists, then fail. */
+			flags |= O_CREAT | O_EXCL;
+			break;
+
+		case OPEN_ALWAYS:
+
+			/* Create if not already exists. */
+			flags |= O_CREAT;
+			break;
+
+		case OPEN_EXISTING:
+
+			/* Default behaviour */
+			break;
+
+		case TRUNCATE_EXISTING:
+
+			/* If the file does not exist, then fail. */
+			flags |= O_TRUNC;
+			break;
+	}
+
+	/*printf("Open: \"%s\"  flags: %X, accessmask: %X sharemode: %X create disp: %X\n", path, flags_and_attributes, accessmask, sharemode, create_disposition); */
+
+	/* Get information about file and set that flag ourselfs */
+	if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))
+	{
+		if (flags_and_attributes & FILE_NON_DIRECTORY_FILE)
+			return RD_STATUS_FILE_IS_A_DIRECTORY;
+		else
+			flags_and_attributes |= FILE_DIRECTORY_FILE;
+	}
+
+	if (flags_and_attributes & FILE_DIRECTORY_FILE)
+	{
+		if (flags & O_CREAT)
+		{
+			mkdir(path, mode);
+		}
+
+		dirp = opendir(path);
+		if (!dirp)
+		{
+			switch (errno)
+			{
+				case EACCES:
+
+					return RD_STATUS_ACCESS_DENIED;
+
+				case ENOENT:
+
+					return RD_STATUS_NO_SUCH_FILE;
+
+				default:
+
+					perror("opendir");
+					return RD_STATUS_NO_SUCH_FILE;
+			}
+		}
+		handle = DIRFD(dirp);
+	}
+	else
+	{
+
+		if (accessmask & GENERIC_ALL
+		    || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE))
+		{
+			flags |= O_RDWR;
+		}
+		else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ))
+		{
+			flags |= O_WRONLY;
+		}
+		else
+		{
+			flags |= O_RDONLY;
+		}
+
+		handle = open_weak_exclusive(path, flags, mode);
+		if (handle == -1)
+		{
+			switch (errno)
+			{
+				case EISDIR:
+
+					return RD_STATUS_FILE_IS_A_DIRECTORY;
+
+				case EACCES:
+
+					return RD_STATUS_ACCESS_DENIED;
+
+				case ENOENT:
+
+					return RD_STATUS_NO_SUCH_FILE;
+				case EEXIST:
+
+					return RD_STATUS_OBJECT_NAME_COLLISION;
+				default:
+
+					perror("open");
+					return RD_STATUS_NO_SUCH_FILE;
+			}
+		}
+
+		/* all read and writes of files should be non blocking */
+		if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1)
+			perror("fcntl");
+	}
+
+	if (handle >= MAX_OPEN_FILES)
+	{
+		error("Maximum number of open files (%s) reached. Increase MAX_OPEN_FILES!\n",
+		      handle);
+		exit(EX_SOFTWARE);
+	}
+
+	if (dirp)
+		g_fileinfo[handle].pdir = dirp;
+	else
+		g_fileinfo[handle].pdir = NULL;
+
+	g_fileinfo[handle].device_id = device_id;
+	g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
+	g_fileinfo[handle].accessmask = accessmask;
+	strncpy(g_fileinfo[handle].path, path, PATH_MAX - 1);
+	g_fileinfo[handle].delete_on_close = False;
+
+	if (accessmask & GENERIC_ALL || accessmask & GENERIC_WRITE)
+		g_notify_stamp = True;
+
+	*phandle = handle;
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+disk_close(RD_NTHANDLE handle)
+{
+	struct fileinfo *pfinfo;
+
+	pfinfo = &(g_fileinfo[handle]);
+
+	if (pfinfo->accessmask & GENERIC_ALL || pfinfo->accessmask & GENERIC_WRITE)
+		g_notify_stamp = True;
+
+	rdpdr_abort_io(handle, 0, RD_STATUS_CANCELLED);
+
+	if (pfinfo->pdir)
+	{
+		if (closedir(pfinfo->pdir) < 0)
+		{
+			perror("closedir");
+			return RD_STATUS_INVALID_HANDLE;
+		}
+
+		if (pfinfo->delete_on_close)
+			if (rmdir(pfinfo->path) < 0)
+			{
+				perror(pfinfo->path);
+				return RD_STATUS_ACCESS_DENIED;
+			}
+		pfinfo->delete_on_close = False;
+	}
+	else
+	{
+		if (close(handle) < 0)
+		{
+			perror("close");
+			return RD_STATUS_INVALID_HANDLE;
+		}
+		if (pfinfo->delete_on_close)
+			if (unlink(pfinfo->path) < 0)
+			{
+				perror(pfinfo->path);
+				return RD_STATUS_ACCESS_DENIED;
+			}
+
+		pfinfo->delete_on_close = False;
+	}
+
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+disk_read(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
+{
+	int n;
+
+#if 0
+	/* browsing dir ????        */
+	/* each request is 24 bytes */
+	if (g_fileinfo[handle].flags_and_attributes & FILE_DIRECTORY_FILE)
+	{
+		*result = 0;
+		return STATUS_SUCCESS;
+	}
+#endif
+
+	lseek(handle, offset, SEEK_SET);
+
+	n = read(handle, data, length);
+
+	if (n < 0)
+	{
+		*result = 0;
+		switch (errno)
+		{
+			case EISDIR:
+				/* Implement 24 Byte directory read ??
+				   with STATUS_NOT_IMPLEMENTED server doesn't read again */
+				/* return STATUS_FILE_IS_A_DIRECTORY; */
+				return RD_STATUS_NOT_IMPLEMENTED;
+			default:
+				perror("read");
+				return RD_STATUS_INVALID_PARAMETER;
+		}
+	}
+
+	*result = n;
+
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+disk_write(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
+{
+	int n;
+
+	lseek(handle, offset, SEEK_SET);
+
+	n = write(handle, data, length);
+
+	if (n < 0)
+	{
+		perror("write");
+		*result = 0;
+		switch (errno)
+		{
+			case ENOSPC:
+				return RD_STATUS_DISK_FULL;
+			default:
+				return RD_STATUS_ACCESS_DENIED;
+		}
+	}
+
+	*result = n;
+
+	return RD_STATUS_SUCCESS;
+}
+
+RD_NTSTATUS
+disk_query_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
+{
+	uint32 file_attributes, ft_high, ft_low;
+	struct stat filestat;
+	char *path, *filename;
+
+	path = g_fileinfo[handle].path;
+
+	/* Get information about file */
+	if (fstat(handle, &filestat) != 0)
+	{
+		perror("stat");
+		out_uint8(out, 0);
+		return RD_STATUS_ACCESS_DENIED;
+	}
+
+	/* Set file attributes */
+	file_attributes = 0;
+	if (S_ISDIR(filestat.st_mode))
+		file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
+
+	filename = 1 + strrchr(path, '/');
+	if (filename && filename[0] == '.')
+		file_attributes |= FILE_ATTRIBUTE_HIDDEN;
+
+	if (!file_attributes)
+		file_attributes |= FILE_ATTRIBUTE_NORMAL;
+
+	if (!(filestat.st_mode & S_IWUSR))
+		file_attributes |= FILE_ATTRIBUTE_READONLY;
+
+	/* Return requested data */
+	switch (info_class)
+	{
+		case FileBasicInformation:
+			seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
+						       &ft_low);
+			out_uint32_le(out, ft_low);	/* create_access_time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* last_access_time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* last_write_time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* last_change_time */
+			out_uint32_le(out, ft_high);
+
+			out_uint32_le(out, file_attributes);
+			break;
+
+		case FileStandardInformation:
+
+			out_uint32_le(out, filestat.st_size);	/* Allocation size */
+			out_uint32_le(out, 0);
+			out_uint32_le(out, filestat.st_size);	/* End of file */
+			out_uint32_le(out, 0);
+			out_uint32_le(out, filestat.st_nlink);	/* Number of links */
+			out_uint8(out, 0);	/* Delete pending */
+			out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0);	/* Directory */
+			break;
+
+		case FileObjectIdInformation:
+
+			out_uint32_le(out, file_attributes);	/* File Attributes */
+			out_uint32_le(out, 0);	/* Reparse Tag */
+			break;
+
+		default:
+
+			unimpl("IRP Query (File) Information class: 0x%x\n", info_class);
+			return RD_STATUS_INVALID_PARAMETER;
+	}
+	return RD_STATUS_SUCCESS;
+}
+
+RD_NTSTATUS
+disk_set_information(RD_NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
+{
+	uint32 length, file_attributes, ft_high, ft_low;
+	char *newname, fullpath[PATH_MAX];
+	struct fileinfo *pfinfo;
+	int mode;
+	struct stat filestat;
+	time_t write_time, change_time, access_time, mod_time;
+	struct utimbuf tvs;
+	struct STATFS_T stat_fs;
+
+	pfinfo = &(g_fileinfo[handle]);
+	g_notify_stamp = True;
+	newname = NULL;
+
+	switch (info_class)
+	{
+		case FileBasicInformation:
+			write_time = change_time = access_time = 0;
+
+			in_uint8s(in, 4);	/* Handle of root dir? */
+			in_uint8s(in, 24);	/* unknown */
+
+			/* CreationTime */
+			in_uint32_le(in, ft_low);
+			in_uint32_le(in, ft_high);
+
+			/* AccessTime */
+			in_uint32_le(in, ft_low);
+			in_uint32_le(in, ft_high);
+			if (ft_low || ft_high)
+				access_time = convert_1970_to_filetime(ft_high, ft_low);
+
+			/* WriteTime */
+			in_uint32_le(in, ft_low);
+			in_uint32_le(in, ft_high);
+			if (ft_low || ft_high)
+				write_time = convert_1970_to_filetime(ft_high, ft_low);
+
+			/* ChangeTime */
+			in_uint32_le(in, ft_low);
+			in_uint32_le(in, ft_high);
+			if (ft_low || ft_high)
+				change_time = convert_1970_to_filetime(ft_high, ft_low);
+
+			in_uint32_le(in, file_attributes);
+
+			if (fstat(handle, &filestat))
+				return RD_STATUS_ACCESS_DENIED;
+
+			tvs.modtime = filestat.st_mtime;
+			tvs.actime = filestat.st_atime;
+			if (access_time)
+				tvs.actime = access_time;
+
+
+			if (write_time || change_time)
+				mod_time = MIN(write_time, change_time);
+			else
+				mod_time = write_time ? write_time : change_time;
+
+			if (mod_time)
+				tvs.modtime = mod_time;
+
+
+			if (access_time || write_time || change_time)
+			{
+#if WITH_DEBUG_RDP5
+				printf("FileBasicInformation access       time %s",
+				       ctime(&tvs.actime));
+				printf("FileBasicInformation modification time %s",
+				       ctime(&tvs.modtime));
+#endif
+				if (utime(pfinfo->path, &tvs) && errno != EPERM)
+					return RD_STATUS_ACCESS_DENIED;
+			}
+
+			if (!file_attributes)
+				break;	/* not valid */
+
+			mode = filestat.st_mode;
+
+			if (file_attributes & FILE_ATTRIBUTE_READONLY)
+				mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+			else
+				mode |= S_IWUSR;
+
+			mode &= 0777;
+#if WITH_DEBUG_RDP5
+			printf("FileBasicInformation set access mode 0%o", mode);
+#endif
+
+			if (fchmod(handle, mode))
+				return RD_STATUS_ACCESS_DENIED;
+
+			break;
+
+		case FileRenameInformation:
+
+			in_uint8s(in, 4);	/* Handle of root dir? */
+			in_uint8s(in, 0x1a);	/* unknown */
+			in_uint32_le(in, length);
+
+			if (length && (length / 2) >= 256)
+				return RD_STATUS_INVALID_PARAMETER;
+
+			rdp_in_unistr(in, length, &newname, &length);
+			if (newname == NULL)
+				return RD_STATUS_INVALID_PARAMETER;
+
+			convert_to_unix_filename(newname);
+
+			sprintf(fullpath, "%s%s", g_rdpdr_device[pfinfo->device_id].local_path,
+				newname);
+
+			free(newname);
+
+			if (rename(pfinfo->path, fullpath) != 0)
+			{
+				perror("rename");
+				return RD_STATUS_ACCESS_DENIED;
+			}
+			break;
+
+		case FileDispositionInformation:
+			/* As far as I understand it, the correct
+			   thing to do here is to *schedule* a delete,
+			   so it will be deleted when the file is
+			   closed. Subsequent
+			   FileDispositionInformation requests with
+			   DeleteFile set to FALSE should unschedule
+			   the delete. See
+			   http://www.osronline.com/article.cfm?article=245. */
+
+			/* FileDispositionInformation always sets delete_on_close to true.
+			   "STREAM in" includes Length(4bytes) , Padding(24bytes) and SetBuffer(zero byte).
+			   Length is always set to zero.
+			   [MS-RDPEFS] http://msdn.microsoft.com/en-us/library/cc241305%28PROT.10%29.aspx
+			   - 2.2.3.3.9 Server Drive Set Information Request
+			 */
+			in_uint8s(in, 4);	/* length of SetBuffer */
+			in_uint8s(in, 24);	/* padding */
+
+
+			if ((pfinfo->accessmask &
+			     (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))
+			{
+				/* if file exists in directory , necessary to return RD_STATUS_DIRECTORY_NOT_EMPTY with win2008
+				   [MS-RDPEFS] http://msdn.microsoft.com/en-us/library/cc241305%28PROT.10%29.aspx
+				   - 2.2.3.3.9 Server Drive Set Information Request
+				   - 2.2.3.4.9 Client Drive Set Information Response
+				   [MS-FSCC] http://msdn.microsoft.com/en-us/library/cc231987%28PROT.10%29.aspx
+				   - 2.4.11 FileDispositionInformation
+				   [FSBO] http://msdn.microsoft.com/en-us/library/cc246487%28PROT.13%29.aspx
+				   - 4.3.2 Set Delete-on-close using FileDispositionInformation Information Class (IRP_MJ_SET_INFORMATION)
+				 */
+				if (pfinfo->pdir)
+				{
+					DIR *dp = opendir(pfinfo->path);
+					struct dirent *dir;
+
+					while ((dir = readdir(dp)) != NULL)
+					{
+						if (strcmp(dir->d_name, ".") != 0
+						    && strcmp(dir->d_name, "..") != 0)
+						{
+							closedir(dp);
+							return RD_STATUS_DIRECTORY_NOT_EMPTY;
+						}
+					}
+					closedir(dp);
+				}
+
+				pfinfo->delete_on_close = True;
+			}
+
+			break;
+
+		case FileAllocationInformation:
+			/* Fall through to FileEndOfFileInformation,
+			   which uses ftrunc. This is like Samba with
+			   "strict allocation = false", and means that
+			   we won't detect out-of-quota errors, for
+			   example. */
+
+		case FileEndOfFileInformation:
+			in_uint8s(in, 28);	/* unknown */
+			in_uint32_le(in, length);	/* file size */
+
+			/* prevents start of writing if not enough space left on device */
+			if (STATFS_FN(pfinfo->path, &stat_fs) == 0)
+				if (stat_fs.f_bfree * stat_fs.f_bsize < length)
+					return RD_STATUS_DISK_FULL;
+
+			if (ftruncate_growable(handle, length) != 0)
+			{
+				return RD_STATUS_DISK_FULL;
+			}
+
+			break;
+		default:
+
+			unimpl("IRP Set File Information class: 0x%x\n", info_class);
+			return RD_STATUS_INVALID_PARAMETER;
+	}
+	return RD_STATUS_SUCCESS;
+}
+
+RD_NTSTATUS
+disk_check_notify(RD_NTHANDLE handle)
+{
+	struct fileinfo *pfinfo;
+	RD_NTSTATUS status = RD_STATUS_PENDING;
+
+	NOTIFY notify;
+
+	pfinfo = &(g_fileinfo[handle]);
+	if (!pfinfo->pdir)
+		return RD_STATUS_INVALID_DEVICE_REQUEST;
+
+
+
+	status = NotifyInfo(handle, pfinfo->info_class, &notify);
+
+	if (status != RD_STATUS_PENDING)
+		return status;
+
+	if (memcmp(&pfinfo->notify, &notify, sizeof(NOTIFY)))
+	{
+		/*printf("disk_check_notify found changed event\n"); */
+		memcpy(&pfinfo->notify, &notify, sizeof(NOTIFY));
+		status = RD_STATUS_NOTIFY_ENUM_DIR;
+	}
+
+	return status;
+
+
+}
+
+RD_NTSTATUS
+disk_create_notify(RD_NTHANDLE handle, uint32 info_class)
+{
+
+	struct fileinfo *pfinfo;
+	RD_NTSTATUS ret = RD_STATUS_PENDING;
+
+	/* printf("start disk_create_notify info_class %X\n", info_class); */
+
+	pfinfo = &(g_fileinfo[handle]);
+	pfinfo->info_class = info_class;
+
+	ret = NotifyInfo(handle, info_class, &pfinfo->notify);
+
+	if (info_class & 0x1000)
+	{			/* ???? */
+		if (ret == RD_STATUS_PENDING)
+			return RD_STATUS_SUCCESS;
+	}
+
+	/* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */
+
+
+	return ret;
+
+}
+
+static RD_NTSTATUS
+NotifyInfo(RD_NTHANDLE handle, uint32 info_class, NOTIFY * p)
+{
+	struct fileinfo *pfinfo;
+	struct stat filestat;
+	struct dirent *dp;
+	char *fullname;
+	DIR *dpr;
+
+	pfinfo = &(g_fileinfo[handle]);
+	if (fstat(handle, &filestat) < 0)
+	{
+		perror("NotifyInfo");
+		return RD_STATUS_ACCESS_DENIED;
+	}
+	p->modify_time = filestat.st_mtime;
+	p->status_time = filestat.st_ctime;
+	p->num_entries = 0;
+	p->total_time = 0;
+
+
+	dpr = opendir(pfinfo->path);
+	if (!dpr)
+	{
+		perror("NotifyInfo");
+		return RD_STATUS_ACCESS_DENIED;
+	}
+
+
+	while ((dp = readdir(dpr)))
+	{
+		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+			continue;
+		p->num_entries++;
+		fullname = (char *) xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2);
+		sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name);
+
+		if (!stat(fullname, &filestat))
+		{
+			p->total_time += (filestat.st_mtime + filestat.st_ctime);
+		}
+
+		xfree(fullname);
+	}
+	closedir(dpr);
+
+	return RD_STATUS_PENDING;
+}
+
+static FsInfoType *
+FsVolumeInfo(char *fpath)
+{
+
+	static FsInfoType info;
+#ifdef USE_SETMNTENT
+	FILE *fdfs;
+	struct mntent *e;
+#endif
+
+	/* initialize */
+	memset(&info, 0, sizeof(info));
+	strcpy(info.label, "RDESKTOP");
+	strcpy(info.type, "RDPFS");
+
+#ifdef USE_SETMNTENT
+	fdfs = setmntent(MNTENT_PATH, "r");
+	if (!fdfs)
+		return &info;
+
+	while ((e = getmntent(fdfs)))
+	{
+		if (str_startswith(e->mnt_dir, fpath))
+		{
+			strcpy(info.type, e->mnt_type);
+			strcpy(info.name, e->mnt_fsname);
+			if (strstr(e->mnt_opts, "vfat") || strstr(e->mnt_opts, "iso9660"))
+			{
+				int fd = open(e->mnt_fsname, O_RDONLY);
+				if (fd >= 0)
+				{
+					unsigned char buf[512];
+					memset(buf, 0, sizeof(buf));
+					if (strstr(e->mnt_opts, "vfat"))
+						 /*FAT*/
+					{
+						strcpy(info.type, "vfat");
+						read(fd, buf, sizeof(buf));
+						info.serial =
+							(buf[42] << 24) + (buf[41] << 16) +
+							(buf[40] << 8) + buf[39];
+						strncpy(info.label, (char *) buf + 43, 10);
+						info.label[10] = '\0';
+					}
+					else if (lseek(fd, 32767, SEEK_SET) >= 0)	/* ISO9660 */
+					{
+						read(fd, buf, sizeof(buf));
+						strncpy(info.label, (char *) buf + 41, 32);
+						info.label[32] = '\0';
+						/* info.Serial = (buf[128]<<24)+(buf[127]<<16)+(buf[126]<<8)+buf[125]; */
+					}
+					close(fd);
+				}
+			}
+		}
+	}
+	endmntent(fdfs);
+#else
+	/* initialize */
+	memset(&info, 0, sizeof(info));
+	strcpy(info.label, "RDESKTOP");
+	strcpy(info.type, "RDPFS");
+
+#endif
+	return &info;
+}
+
+
+RD_NTSTATUS
+disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
+{
+	struct STATFS_T stat_fs;
+	struct fileinfo *pfinfo;
+	FsInfoType *fsinfo;
+
+	pfinfo = &(g_fileinfo[handle]);
+
+	if (STATFS_FN(pfinfo->path, &stat_fs) != 0)
+	{
+		perror("statfs");
+		return RD_STATUS_ACCESS_DENIED;
+	}
+
+	fsinfo = FsVolumeInfo(pfinfo->path);
+
+	switch (info_class)
+	{
+		case FileFsVolumeInformation:
+
+			out_uint32_le(out, 0);	/* volume creation time low */
+			out_uint32_le(out, 0);	/* volume creation time high */
+			out_uint32_le(out, fsinfo->serial);	/* serial */
+
+			out_uint32_le(out, 2 * strlen(fsinfo->label));	/* length of string */
+
+			out_uint8(out, 0);	/* support objects? */
+			rdp_out_unistr(out, fsinfo->label, 2 * strlen(fsinfo->label) - 2);
+			break;
+
+		case FileFsSizeInformation:
+
+			out_uint32_le(out, stat_fs.f_blocks);	/* Total allocation units low */
+			out_uint32_le(out, 0);	/* Total allocation high units */
+			out_uint32_le(out, stat_fs.f_bfree);	/* Available allocation units */
+			out_uint32_le(out, 0);	/* Available allowcation units */
+			out_uint32_le(out, stat_fs.f_bsize / 0x200);	/* Sectors per allocation unit */
+			out_uint32_le(out, 0x200);	/* Bytes per sector */
+			break;
+
+		case FileFsFullSizeInformation:
+
+			out_uint32_le(out, stat_fs.f_blocks);	/* Total allocation units low */
+			out_uint32_le(out, 0);	/* Total allocation units high */
+			out_uint32_le(out, stat_fs.f_bavail);	/* Caller allocation units low */
+			out_uint32_le(out, 0);	/* Caller allocation units high */
+			out_uint32_le(out, stat_fs.f_bfree);	/* Available allocation units */
+			out_uint32_le(out, 0);	/* Available allowcation units */
+			out_uint32_le(out, stat_fs.f_bsize / 0x200);	/* Sectors per allocation unit */
+			out_uint32_le(out, 0x200);	/* Bytes per sector */
+			break;
+
+		case FileFsAttributeInformation:
+
+			out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED);	/* fs attributes */
+			out_uint32_le(out, F_NAMELEN(stat_fs));	/* max length of filename */
+
+			out_uint32_le(out, 2 * strlen(fsinfo->type));	/* length of fs_type */
+			rdp_out_unistr(out, fsinfo->type, 2 * strlen(fsinfo->type) - 2);
+			break;
+
+		case FileFsLabelInformation:
+		case FileFsDeviceInformation:
+		case FileFsControlInformation:
+		case FileFsObjectIdInformation:
+		case FileFsMaximumInformation:
+
+		default:
+
+			unimpl("IRP Query Volume Information class: 0x%x\n", info_class);
+			return RD_STATUS_INVALID_PARAMETER;
+	}
+	return RD_STATUS_SUCCESS;
+}
+
+RD_NTSTATUS
+disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREAM out)
+{
+	uint32 file_attributes, ft_low, ft_high;
+	char *dirname, fullpath[PATH_MAX];
+	DIR *pdir;
+	struct dirent *pdirent;
+	struct stat filestat;
+	struct fileinfo *pfinfo;
+
+	pfinfo = &(g_fileinfo[handle]);
+	pdir = pfinfo->pdir;
+	dirname = pfinfo->path;
+	file_attributes = 0;
+
+
+	switch (info_class)
+	{
+		case FileBothDirectoryInformation:
+		case FileDirectoryInformation:
+		case FileFullDirectoryInformation:
+		case FileNamesInformation:
+
+			/* If a search pattern is received, remember this pattern, and restart search */
+			if (pattern != NULL && pattern[0] != 0)
+			{
+				strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), PATH_MAX - 1);
+				rewinddir(pdir);
+			}
+
+			/* find next dirent matching pattern */
+			pdirent = readdir(pdir);
+			while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)
+				pdirent = readdir(pdir);
+
+			if (pdirent == NULL)
+				return RD_STATUS_NO_MORE_FILES;
+
+			/* Get information for directory entry */
+			sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
+
+			if (stat(fullpath, &filestat))
+			{
+				switch (errno)
+				{
+					case ENOENT:
+					case ELOOP:
+					case EACCES:
+						/* These are non-fatal errors. */
+						memset(&filestat, 0, sizeof(filestat));
+						break;
+					default:
+						/* Fatal error. By returning STATUS_NO_SUCH_FILE, 
+						   the directory list operation will be aborted */
+						perror(fullpath);
+						out_uint8(out, 0);
+						return RD_STATUS_NO_SUCH_FILE;
+				}
+			}
+
+			if (S_ISDIR(filestat.st_mode))
+				file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
+			if (pdirent->d_name[0] == '.')
+				file_attributes |= FILE_ATTRIBUTE_HIDDEN;
+			if (!file_attributes)
+				file_attributes |= FILE_ATTRIBUTE_NORMAL;
+			if (!(filestat.st_mode & S_IWUSR))
+				file_attributes |= FILE_ATTRIBUTE_READONLY;
+
+			/* Return requested information */
+			out_uint32_le(out, 0);	/* NextEntryOffset */
+			out_uint32_le(out, 0);	/* FileIndex zero */
+			break;
+
+		default:
+			unimpl("IRP Query Directory sub: 0x%x\n", info_class);
+			return RD_STATUS_INVALID_PARAMETER;
+	}
+
+	switch (info_class)
+	{
+		case FileBothDirectoryInformation:
+
+			seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
+						       &ft_low);
+			out_uint32_le(out, ft_low);	/* create time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* last_access_time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* last_write_time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* change_write_time */
+			out_uint32_le(out, ft_high);
+
+			out_uint32_le(out, filestat.st_size);	/* filesize low */
+			out_uint32_le(out, 0);	/* filesize high */
+			out_uint32_le(out, filestat.st_size);	/* filesize low */
+			out_uint32_le(out, 0);	/* filesize high */
+			out_uint32_le(out, file_attributes);	/* FileAttributes */
+			out_uint32_le(out, 2 * strlen(pdirent->d_name) + 2);	/* unicode length */
+			out_uint32_le(out, 0);	/* EaSize */
+			out_uint8(out, 0);	/* ShortNameLength */
+			/* this should be correct according to MS-FSCC specification
+			   but it only works when commented out... */
+			/* out_uint8(out, 0); *//* Reserved/Padding */
+			out_uint8s(out, 2 * 12);	/* ShortName (8.3 name) */
+			rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
+			break;
+
+
+		case FileDirectoryInformation:
+
+			seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
+						       &ft_low);
+			out_uint32_le(out, ft_low);	/* create time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* last_access_time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* last_write_time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* change_write_time */
+			out_uint32_le(out, ft_high);
+
+			out_uint32_le(out, filestat.st_size);	/* filesize low */
+			out_uint32_le(out, 0);	/* filesize high */
+			out_uint32_le(out, filestat.st_size);	/* filesize low */
+			out_uint32_le(out, 0);	/* filesize high */
+			out_uint32_le(out, file_attributes);
+			out_uint32_le(out, 2 * strlen(pdirent->d_name) + 2);	/* unicode length */
+			rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
+			break;
+
+
+		case FileFullDirectoryInformation:
+
+			seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
+						       &ft_low);
+			out_uint32_le(out, ft_low);	/* create time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* last_access_time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* last_write_time */
+			out_uint32_le(out, ft_high);
+
+			seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
+			out_uint32_le(out, ft_low);	/* change_write_time */
+			out_uint32_le(out, ft_high);
+
+			out_uint32_le(out, filestat.st_size);	/* filesize low */
+			out_uint32_le(out, 0);	/* filesize high */
+			out_uint32_le(out, filestat.st_size);	/* filesize low */
+			out_uint32_le(out, 0);	/* filesize high */
+			out_uint32_le(out, file_attributes);
+			out_uint32_le(out, 2 * strlen(pdirent->d_name) + 2);	/* unicode length */
+			out_uint32_le(out, 0);	/* EaSize */
+			rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
+			break;
+
+
+		case FileNamesInformation:
+
+			out_uint32_le(out, 2 * strlen(pdirent->d_name) + 2);	/* unicode length */
+			rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
+			break;
+
+
+		default:
+
+			unimpl("IRP Query Directory sub: 0x%x\n", info_class);
+			return RD_STATUS_INVALID_PARAMETER;
+	}
+
+	return RD_STATUS_SUCCESS;
+}
+
+
+
+static RD_NTSTATUS
+disk_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
+{
+	if (((request >> 16) != 20) || ((request >> 16) != 9))
+		return RD_STATUS_INVALID_PARAMETER;
+
+	/* extract operation */
+	request >>= 2;
+	request &= 0xfff;
+
+	printf("DISK IOCTL %d\n", request);
+
+	switch (request)
+	{
+		case 25:	/* ? */
+		case 42:	/* ? */
+		default:
+			unimpl("DISK IOCTL %d\n", request);
+			return RD_STATUS_INVALID_PARAMETER;
+	}
+
+	return RD_STATUS_SUCCESS;
+}
+
+DEVICE_FNS disk_fns = {
+	disk_create,
+	disk_close,
+	disk_read,
+	disk_write,
+	disk_device_control	/* device_control */
+};
Index: /trunk/src/VBox/RDP/client-1.8.3/disk.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/disk.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/disk.h	(revision 55121)
@@ -0,0 +1,140 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   Disk Redirection definitions
+   Copyright (C) Jeroen Meijer 2003-2008
+   Copyright (C) Peter Astrand 2004-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define FILE_ATTRIBUTE_READONLY			0x00000001
+#define FILE_ATTRIBUTE_HIDDEN			0x00000002
+#define FILE_ATTRIBUTE_SYSTEM			0x00000004
+#define FILE_ATTRIBUTE_DIRECTORY		0x00000010
+#define FILE_ATTRIBUTE_ARCHIVE			0x00000020
+#define FILE_ATTRIBUTE_DEVICE			0x00000040
+#define FILE_ATTRIBUTE_UNKNOWNXXX0		0x00000060	/* ??? ACTION i.e. 0x860 == compress this file ? */
+#define FILE_ATTRIBUTE_NORMAL			0x00000080
+#define FILE_ATTRIBUTE_TEMPORARY		0x00000100
+#define FILE_ATTRIBUTE_SPARSE_FILE		0x00000200
+#define FILE_ATTRIBUTE_REPARSE_POINT		0x00000400
+#define FILE_ATTRIBUTE_COMPRESSED		0x00000800
+#define FILE_ATTRIBUTE_OFFLINE			0x00001000
+#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED	0x00002000
+#define FILE_ATTRIBUTE_ENCRYPTED		0x00004000
+
+#define FILE_FLAG_OPEN_NO_RECALL		0x00100000
+#define FILE_FLAG_OPEN_REPARSE_POINT		0x00200000
+#define FILE_FLAG_POSIX_SEMANTICS		0x01000000
+#define FILE_FLAG_BACKUP_SEMANTICS		0x02000000	/* sometimes used to create a directory */
+#define FILE_FLAG_DELETE_ON_CLOSE		0x04000000
+#define FILE_FLAG_SEQUENTIAL_SCAN		0x08000000
+#define FILE_FLAG_RANDOM_ACCESS			0x10000000
+#define FILE_FLAG_NO_BUFFERING			0x20000000
+#define FILE_FLAG_OVERLAPPED			0x40000000
+#define FILE_FLAG_WRITE_THROUGH			0x80000000
+
+#define FILE_SHARE_READ				0x01
+#define FILE_SHARE_WRITE			0x02
+#define FILE_SHARE_DELETE			0x04
+
+#define FILE_BASIC_INFORMATION			0x04
+#define FILE_STANDARD_INFORMATION		0x05
+
+#define FS_CASE_SENSITIVE			0x00000001
+#define FS_CASE_IS_PRESERVED			0x00000002
+#define FS_UNICODE_STORED_ON_DISK		0x00000004
+#define FS_PERSISTENT_ACLS			0x00000008
+#define FS_FILE_COMPRESSION			0x00000010
+#define FS_VOLUME_QUOTAS			0x00000020
+#define FS_SUPPORTS_SPARSE_FILES		0x00000040
+#define FS_SUPPORTS_REPARSE_POINTS		0x00000080
+#define FS_SUPPORTS_REMOTE_STORAGE		0X00000100
+#define FS_VOL_IS_COMPRESSED			0x00008000
+#define FILE_READ_ONLY_VOLUME			0x00080000
+
+#define OPEN_EXISTING				1
+#define CREATE_NEW				2
+#define OPEN_ALWAYS				3
+#define TRUNCATE_EXISTING			4
+#define CREATE_ALWAYS				5
+
+#define GENERIC_READ				0x80000000
+#define GENERIC_WRITE				0x40000000
+#define GENERIC_EXECUTE				0x20000000
+#define GENERIC_ALL				0x10000000
+
+#define ERROR_FILE_NOT_FOUND			2L
+#define ERROR_ALREADY_EXISTS			183L
+
+#define	MAX_OPEN_FILES	0x100
+
+typedef enum _FILE_INFORMATION_CLASS
+{
+	FileDirectoryInformation = 1,
+	FileFullDirectoryInformation,
+	FileBothDirectoryInformation,
+	FileBasicInformation,
+	FileStandardInformation,
+	FileInternalInformation,
+	FileEaInformation,
+	FileAccessInformation,
+	FileNameInformation,
+	FileRenameInformation,
+	FileLinkInformation,
+	FileNamesInformation,
+	FileDispositionInformation,
+	FilePositionInformation,
+	FileFullEaInformation,
+	FileModeInformation,
+	FileAlignmentInformation,
+	FileAllInformation,
+	FileAllocationInformation,
+	FileEndOfFileInformation,
+	FileAlternateNameInformation,
+	FileStreamInformation,
+	FilePipeInformation,
+	FilePipeLocalInformation,
+	FilePipeRemoteInformation,
+	FileMailslotQueryInformation,
+	FileMailslotSetInformation,
+	FileCompressionInformation,
+	FileCopyOnWriteInformation,
+	FileCompletionInformation,
+	FileMoveClusterInformation,
+	FileOleClassIdInformation,
+	FileOleStateBitsInformation,
+	FileNetworkOpenInformation,
+	FileObjectIdInformation,
+	FileOleAllInformation,
+	FileOleDirectoryInformation,
+	FileContentIndexInformation,
+	FileInheritContentIndexInformation,
+	FileOleInformation,
+	FileMaximumInformation
+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
+
+typedef enum _FSINFOCLASS
+{
+	FileFsVolumeInformation = 1,
+	FileFsLabelInformation,
+	FileFsSizeInformation,
+	FileFsDeviceInformation,
+	FileFsAttributeInformation,
+	FileFsControlInformation,
+	FileFsFullSizeInformation,
+	FileFsObjectIdInformation,
+	FileFsDriverPathInformation,
+	FileFsMaximumInformation
+} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;
Index: /trunk/src/VBox/RDP/client-1.8.3/doc/AUTHORS
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/doc/AUTHORS	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/doc/AUTHORS	(revision 55121)
@@ -0,0 +1,20 @@
+This is an attempt at a list of people who have made significant
+contributions to the code.  If you have been unintentionally omitted
+please let one of the team members know.
+
+Alexi Volkov <alexi@myrealbox.com>
+Erik Forsberg <forsberg@cendio.se>
+GuoJunBo <guojunbo@ict.ac.cn>
+Henrik Andersson <hean01@cendio.se> for Cendio AB
+Hugo Trippaers <spark@ision.nl>
+Jay Sorg <j@american-data.com>
+Jeremy Meng <void.foo@gmail.com>
+Jeroen Meijer <jeroen@oldambt7.com>
+Matrox Graphics Inc.
+Matthew Chapman <matthewc.unsw.edu.au>
+Michael Gernoth <mike@zerfleddert.de>
+Michal Mihalik <mmihalik@sme.sk>
+Norbert Federa <nob@thinstuff.com>
+Peter Astrand <astrand@cendio.se> for Cendio AB
+Peter Kallden <peter.kallden@ub.oru.se>
+Pierre Ossman <ossman@cendio.se> for Cendio AB
Index: /trunk/src/VBox/RDP/client-1.8.3/doc/ChangeLog
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/doc/ChangeLog	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/doc/ChangeLog	(revision 55121)
@@ -0,0 +1,204 @@
+rdesktop (1.8.3)
+  * Added a persistent mode used with SeamlessRDP
+  * Added US international keyboard layout with dead keys
+  * Code cleanup to match specifications, use constants defined
+    instead of magic numbers, remove of dead code
+  * Fix regression with failed connection and a invalid licensing
+    message, introduced in 1.8.2
+  * Fix issue with Non ASCII user / password when using CredSSP
+  * Fix issues using smartcard redirection with Windows 2012 R2
+  * Fix issue with windows key functionality
+  * Fix memory corruption when using rdp_out_unistr()
+  * Fix workaround for the lack of support for alpha cursors
+  * Fix silent exit when redirected when using CredSSP
+  * Fix crash when starting rdesktop without domain specified
+    while using CredSSP
+  * Fix issue in SeamlessRDP protocol parser upon reconnect
+  * Fix issue were a new SeamlessRDP application is respawned
+    upon a reconnection
+
+  -- Henrik Andersson <hean01@users.sourceforge.net> 2014-10-31
+
+rdesktop (1.8.2)
+  * Support enhanced server redirection (Session broker 2012)
+  * Support License Error Alert PDU
+  * Changed default driver for printer redirection
+  * Fix CredSSP login using non-ASCII username/password
+  * Fix double login prompt bug with Win2008 server redirection
+  * Fix keysym collisions
+  * Fix mouse cursor with 2012 R2
+  * Fix local drive redirection with Win8 / Win2012
+  * Fix issue with mouse cursor hotspot
+  * Fix issue with mouse / keyboard against VirtualBox RDP
+  * Fix uncomplete czech keymap
+  * Fix error in dutch keymap
+
+  -- Henrik Andersson <hean01@users.sourceforge.net> 2014-05-20
+
+rdesktop (1.8.1)
+  * Fix a typo in configure.ac
+  * Fix a bug which made rdesktop steal CPU cycles.
+  * Fix issue with reconnect, make use of deactivate variable
+  * Added 4 new disconnect reasons with exit codes
+  * Fix issues of window handling in SeamlessRDP parts of rdesktop
+  * Fix a backward compability with OpenSSL < 0.9.9
+  * Fix a bug when code needs a x window available but there are none.
+  * Fix a sigsegv zeroing memory
+  * Fix a 64bit portability issue
+
+  -- Henrik Andersson <hean01@users.sourceforge.net> 2013-11-18
+
+rdesktop (1.8.0)
+  * Support for protocol negotiation eg. SSL/TLSv1 and CredSSP
+  * Support for CredSSP + Kerberos authentication (NLA)
+  * Support for smart card single-sign-on
+  * Support passing smart card pin as password as argument
+  * Added IPC for controlling a master rdesktop process
+  * Support for connection sharing when using SeamlessRDP
+  * Improved handling of network connection failures
+  * Autoreconnect using the connection cookie at network failure
+  * Fix a few smart card issues
+  * Fix bug with mouse scroll handling
+  * Fix for left/right braces in Italian keymap
+  * Fix crash and memory leak in local drive redirection
+  * Fixes issues with license files loading/saving
+
+  -- Henrik Andersson <hean01@users.sourceforge.net> 2013-08-09
+
+rdesktop (1.7.1)
+  * Fix clipboard issue when not building with unicode support
+  * Fix compilation against newer PCSC lite versions
+  * Fix for per-device license mode on Windows 2008 R2 terminal server
+  * Fix building 64bit version with static openssl linkage
+  * Rewrite of smartcard handling for 64bit support, fixes several bugs
+  * Improved license handling using XDG directories
+
+  -- Henrik Andersson <hean01@users.sourceforge.net> 2012-01-09
+
+rdesktop (1.7.0)
+  * Security: Directory traversal vulnerability with disk redirection (disallow /.. requests)
+  * New maintainer: Peter Åstrand <astrand@cendio.se>
+  * Brush cache support
+  * Removed the hardcoded limit of the username length
+  * Increased domain name length to 255 chars
+  * Improved compatibility with PulseAudio/padsp
+  * Cleaned up and documented the return values
+  * Keyboard fix: avoid stuck keys in certain cases
+  * Support for new pointers
+  * License has been changed to GPLv3
+  * EWMH fixes for 64-bit machines
+  * RandR support: automatically resize session if using relative screen size
+  * Improved support for Windows 2008 Session Broker
+  * Japanese keyboard map has been improved
+  * New keyboard map: fr-bepo
+  * Many stability fixes regarding smart card redirection
+  * Windows 2008 R2 / 7: Fix sound playback when not using other redirections
+  * Windows 2008 R2 / 7: Solve disk redirection read-only issues
+  * Windows 2008 R2 / 7: Solve issue with recursive deletion
+  * Avoid exit when printing, if lpr command terminates early
+
+  -- Peter Åstrand <astrand@cendio.se> 2011-04-13
+
+rdesktop (1.6.0)
+  * Fix for crash with recent versions of X.Org
+  * Fix for potential vulnerability against compromised/malicious servers (reported by iDefense)
+  * Fix for Windows 2008 Server
+  * ALSA driver added
+  * Sound drivers can now be selected at runtime
+  * Smartcard support (Alexi Volkov <alexi@myrealbox.com>)
+  * Send physical mouse buttons rather than logical ones
+
+  -- Matthew Chapman <matthewc@cse.unsw.edu.au>  Sat, 11 May 2008 16:12:20 +1100 (AEDT)
+
+rdesktop (1.5.0)
+  * SeamlessRDP - seamless windows support
+  * Keymap fixes
+  * Fix connection issues with Windows XP RTM
+  * Keyboard handling improvements and fixes
+  * SGI/Irix sound-driver fixes
+  * Support for clipboard INCR protocol
+  * Session Directory support (patch from Brian Chapeau <lheria@users.sourceforge.net>)
+  * Support for long filenames on redirected drives
+  * XOR ellipse drawing fix
+  * Clipboard unicode support (Ilya Konstantinov)
+  * Fix display issues with exotic color depths (30bpp, 32bpp, etc) (Ilya Konstantinov)
+  * Large file support
+  * The default color depth is now the depth of the root window
+  * Basic support for Windows Vista Beta 2
+  * Fix high cpu-usage in OSS-driver
+
+  -- Peter Astrand <astrand@cendio.se>  Wed, 13 Sep 2006 15:11:39 +0200 (CEST)
+
+rdesktop (1.4.1)
+   * persistent bitmap cache optimisations
+   * support for more RDP-orders (ellipse, polygon)
+   * libao sound-driver (for Mac OSX and others)
+   * Unicode support for transmitted strings/filenames
+   * Added korean keymap
+   * Xembed fixes to work with krdc correctly
+   * Portability fixes
+   * Support for RDP-compression (all bpps)
+   * process RDP recv queue if send queue is full (Debian bug #246461)
+   * SGI/Irix sound-driver fixes
+
+  -- Michael Gernoth <michael@gernoth.net>  Sun, 8 May 2005 19:55:35 +0200 (CEST)
+
+rdesktop (1.4.0)
+   * Basic disk-, parallel-, printer- and serial-redirection
+   * Fix timezone-redirection
+   * Backing-store fixes
+   * Fix client-IP sent to TS
+   * XEmbed support for embedding rdesktop in other applications (KRDC)
+   * Support for setting the RDP5 experience
+   * Keyboard and keymap fixes
+   * Performance improvements
+   * Report disconnect-reason
+   * Support for RDP-compression (currently only for 8bpp)
+   * Support for persistent bitmap caching
+   * Sound-driver for SGI/Irix
+
+  -- Michael Gernoth <michael@gernoth.net>  Sun, 6 Mar 2005 22:09:55 +0100 (CET)
+
+rdesktop (1.3.1)
+   * Crypto fixes for RDP5
+   * Keyboard and keymap fixes
+   * some endianess fixes for high color
+   * portability enhancements
+
+  -- Matthew Chapman <matthewc@cse.unsw.edu.au>  Tue, 21 Jan 2004 20:34
+
+rdesktop (1.3.0)
+
+   * RDP5
+   * 15, 16 and 24 bit color depths
+   * Basic clipboard redirection
+   * Sound
+   * IPv6
+   * Attaching to console on Windows 2003
+
+  -- Peter Astrand <astrand@cendio.se>  Wed, 29 Oct 2003 16:40:58 +0100 (CET)
+
+rdesktop (1.2.0)
+
+   * new - more portable - key mapping code
+   * support for "high" (128-bit) encryption
+   * toggling out of full-screen mode with Ctrl-Alt-Enter
+   * a few extra options including host:port syntax
+   * many, many bug fixes and optimisations
+
+  -- Matthew Chapman <matthewc@cse.unsw.edu.au>  Thu, 30 Jan 2003 04:29
+
+rdesktop (1.1.0)
+
+   * solves arith.c licensing issue by taking big number routines from
+     OpenSSL
+   * keyboard support not merged from unified patches yet
+   * still no manpage
+
+  -- Matthew Chapman <matthewc@cse.unsw.edu.au>  Mon, 17 Sep 2001 23:14:28 +1000 (AEST)
+
+rdesktop (1.0.0)
+
+   * initial release
+
+  -- Matthew Chapman <matthewc@cse.unsw.edu.au>
Index: /trunk/src/VBox/RDP/client-1.8.3/doc/HACKING
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/doc/HACKING	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/doc/HACKING	(revision 55121)
@@ -0,0 +1,45 @@
+
+Code style / indentation
+------------------------
+The file indent-all.sh contains information about the current code
+style.  Run this script before commits.
+
+
+Variable argument macros
+------------------------
+Variable argument macros are non-portable in general, and should be
+avoided.  Either use a second set of parentheses like DEBUG, or create
+a variable argument function like error.
+
+
+Structure
+---------
+The core protocol stack should be system-independent (i.e. ANSI C89
+only) so that it is easy to port. This currently applies to the
+following files:
+
+bitmap.c licence.c orders.c rdp.c rdp5.c cache.c iso.c mcs.c
+secure.c mppc.c channels.c
+rdesktop.c
+
+
+Compiler support
+----------------
+
+The source code should be compatible with ANSI C89. One exception is
+the SeamlessRDP ServerEXE and ClientDLL, which should be compatible
+with ANSI C99.
+
+
+RDP resources
+-------------
+http://dev.remotenetworktechnology.com/refdata.htm
+
+
+Checking for out of memory conditions
+-------------------------------------
+Try to handle out of memory conditions gracefully. Use the xmalloc
+routines from rdesktop.c, instead of calling malloc manually. Also,
+remember that several Xlib functions can return NULL. This includes
+XGetImage. Use exit_if_null to verify returned pointers. 
+
Index: /trunk/src/VBox/RDP/client-1.8.3/doc/TODO
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/doc/TODO	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/doc/TODO	(revision 55121)
@@ -0,0 +1,102 @@
+* General
+
+  * Rework main loop to a generic event handler (i.e. move select() to
+    the top of the stack, not the end). Also means rewriting the connect
+    procedure as a state machine.
+
+  * Stop using static objects for packets and make it more clear when it
+    is in use (explicit allocation and free).
+
+* Clipboard:
+
+  * Support other data types than plain text. 
+ 
+  * Conversion between different character sets. 
+
+
+* Drive Redirection:
+
+  * Real support for file locking
+
+  * Handle reconnections correctly. 
+
+  * Various deficiencies; see FIXMEs in source code. 
+
+
+* Serial Port Redirection:
+
+  * More testing needed. 
+
+
+* Printer Redirection:
+
+  * More testing needed. 
+
+
+* Keymapping: 
+
+
+* Sound redirection
+
+  * Use timestamps in audio packets.
+
+  * Add resampling to supported samplerates of audio-hardware.
+
+  * Lower CPU-usage with an audio thread.
+
+
+* Smartcard redirection
+
+  * Merge patches currently implementing sc-redirection.
+
+
+* Miscellaneous
+
+  * Clean up header files. The current "proto.h" and "xproto.h" is far
+    from optimal.
+
+  * Go through the many trackers (bugs/patches/RFEs) at SourceForge. 
+
+  * More fancy homepage. 
+
+  * Enhance documentation. Write a FAQ. 
+
+
+* SeamlessRDP mode
+
+  * Add a client to server message for starting additional
+    applications.
+
+  * Support cmd.exe. 
+
+  * Support for Input Contexts. 
+
+  * Enhanced support for WM_DELETE_WINDOW: Instead of terminating
+    rdesktop, close the window on the server side. 
+
+  * Systray support. 
+
+  * Better support for non-EWMH window managers. 
+
+  * Support for non-rectangular windows. 
+
+  * The focus handling of menus is a bit crude. 
+
+  * Support for sending focus information from client to server.
+
+  * Implement something similiar to explhook.dll - support for running
+    explorer.exe in non-shell mode. 
+
+  * Better compatibility with Task Manager. 
+
+  * XINERAMA support.  
+
+  * When enumerating windows, make sure to send info about windows
+    that are transient for other windows after the referred window.
+
+  * We support topmost windows at creating time, but we do not detect
+    when this property is added or removed. This can be verified with
+    task manager, which has an "Always on top" option. 
+
+  * Window icons are not set when reconnecting. get_icon/update_icon
+    needs to be called from enum_cb. 
Index: /trunk/src/VBox/RDP/client-1.8.3/doc/ipv6.txt
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/doc/ipv6.txt	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/doc/ipv6.txt	(revision 55121)
@@ -0,0 +1,29 @@
+
+IPv6 support in rdesktop
+========================
+The IPv6 support was developed by Mike Dawson <mike@dexy.mine.nu>:
+
+    Attached is a patch to tcp.c to enable IPv6 support.  Build with
+    'IPv6' defined to enable it.  It's so far only been tested on
+    Linux 2.4.21 connecting to Windows XP SP1.
+    
+    Since terminal services doesn't seem to bind to the ipv6 interface
+    on XP I had to run 'netsh interface portproxy add v6tov4
+    listenport=3389 connectport=3389' from the windows command prompt
+    to get it to work.
+    
+
+rdesktop now supports numeric IPv6 addresses:
+
+    It checks for two or more colons in an address to decide what it's
+    dealing with so you can now do:
+
+    rdesktop 2001:1:2:3::4
+    
+    without it getting confused with an ipv4:port specification.  I've
+    also followed the square bracket convention used by browsers
+    (http://www.ietf.org/rfc/rfc2732.txt) so if you want to specify a
+    non-standard port with an ipv6 address you can use the format:
+    
+    rdesktop [2001:1:2:3::4]:3390
+
Index: /trunk/src/VBox/RDP/client-1.8.3/doc/keymap-names.txt
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/doc/keymap-names.txt	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/doc/keymap-names.txt	(revision 55121)
@@ -0,0 +1,124 @@
+
+0x0436 af Afrikaans
+0x041C sq Albanian
+0x0001 ar Arabic
+0x0401 ar-sa Arabic (Saudi Arabia)
+0x0801 ar-iq Arabic (Iraq)
+0x0C01 ar-eg Arabic (Egypt)
+0x1001 ar-ly Arabic (Libya)
+0x1401 ar-dz Arabic (Algeria)
+0x1801 ar-ma Arabic (Morocco)
+0x1C01 ar-tn Arabic (Tunisia)
+0x2001 ar-om Arabic (Oman)
+0x2401 ar-ye Arabic (Yemen)
+0x2801 ar-sy Arabic (Syria)
+0x2C01 ar-jo Arabic (Jordan)
+0x3001 ar-lb Arabic (Lebanon)
+0x3401 ar-kw Arabic (Kuwait)
+0x3801 ar-ae Arabic (U.A.E.)
+0x3C01 ar-bh Arabic (Bahrain)
+0x4001 ar-qa Arabic (Qatar)
+0x042D eu Basque
+0x0402 bg Bulgarian
+0x0423 be Belarusian
+0x0403 ca Catalan
+0x0004 zh Chinese
+0x0404 zh-tw Chinese (Taiwan)
+0x0804 zh-cn Chinese (China)
+0x0C04 zh-hk Chinese (Hong Kong SAR)
+0x1004 zh-sg Chinese (Singapore)
+0x041A hr Croatian
+0x0405 cs Czech
+0x0406 da Danish
+0x0413 nl Dutch (Netherlands)
+0x0813 nl-be Dutch (Belgium)
+0x0009 en English
+0x0409 en-us English (United States)
+0x0809 en-gb English (United Kingdom)
+0x0C09 en-au English (Australia)
+0x1009 en-ca English (Canada)
+0x1409 en-nz English (New Zealand)
+0x1809 en-ie English (Ireland)
+0x1C09 en-za English (South Africa)
+0x2009 en-jm English (Jamaica)
+0x2809 en-bz English (Belize)
+0x2C09 en-tt English (Trinidad)
+0x0425 et Estonian
+0x0438 fo Faeroese
+0x0429 fa Farsi
+0x040B fi Finnish
+0x040C fr French (France)
+0x080C fr-be French (Belgium)
+0x0C0C fr-ca French (Canada)
+0x100C fr-ch French (Switzerland)
+0x140C fr-lu French (Luxembourg)
+0x043C gd Gaelic
+0x0407 de German (Germany)
+0x0807 de-ch German (Switzerland)
+0x0C07 de-at German (Austria)
+0x1007 de-lu German (Luxembourg)
+0x1407 de-li German (Liechtenstein)
+0x0408 el Greek
+0x040D he Hebrew
+0x0439 hi Hindi
+0x040E hu Hungarian
+0x040F is Icelandic
+0x0421 in Indonesian
+0x0410 it Italian (Italy)
+0x0810 it-ch Italian (Switzerland)
+0x0411 ja Japanese
+0x0412 ko Korean
+0x0426 lv Latvian
+0x0427 lt Lithuanian
+0x042F mk FYRO Macedonian
+0x043E ms Malay (Malaysia)
+0x043A mt Maltese
+0x0414 no Norwegian (Bokmal)
+0x0814 no Norwegian (Nynorsk)
+0x0415 pl Polish
+0x0416 pt-br Portuguese (Brazil)
+0x0816 pt Portuguese (Portugal)
+0x0417 rm Rhaeto-Romanic
+0x0418 ro Romanian
+0x0818 ro-mo Romanian (Moldova)
+0x0419 ru Russian
+0x0819 ru-mo Russian (Moldova)
+0x0C1A sr Serbian (Cyrillic)
+0x081A sr Serbian (Latin)
+0x041B sk Slovak
+0x0424 sl Slovenian
+0x042E sb Sorbian
+0x040A es Spanish (Traditional Sort)
+0x080A es-mx Spanish (Mexico)
+0x0C0A es Spanish (International Sort)
+0x100A es-gt Spanish (Guatemala)
+0x140A es-cr Spanish (Costa Rica)
+0x180A es-pa Spanish (Panama)
+0x1C0A es-do Spanish (Dominican Republic)
+0x200A es-ve Spanish (Venezuela)
+0x240A es-co Spanish (Colombia)
+0x280A es-pe Spanish (Peru)
+0x2C0A es-ar Spanish (Argentina)
+0x300A es-ec Spanish (Ecuador)
+0x340A es-cl Spanish (Chile)
+0x380A es-uy Spanish (Uruguay)
+0x3C0A es-py Spanish (Paraguay)
+0x400A es-bo Spanish (Bolivia)
+0x440A es-sv Spanish (El Salvador)
+0x480A es-hn Spanish (Honduras)
+0x4C0A es-ni Spanish (Nicaragua)
+0x500A es-pr Spanish (Puerto Rico)
+0x0430 sx Sutu
+0x041D sv Swedish
+0x081D sv-fi Swedish (Finland)
+0x041E th Thai
+0x0431 ts Tsonga
+0x0432 tn Tswana
+0x041F tr Turkish
+0x0422 uk Ukrainian
+0x0420 ur Urdu
+0x042A vi Vietnamese
+0x0434 xh Xhosa
+0x043D ji Yiddish
+0x0435 zu Zulu
+
Index: /trunk/src/VBox/RDP/client-1.8.3/doc/keymapping.txt
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/doc/keymapping.txt	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/doc/keymapping.txt	(revision 55121)
@@ -0,0 +1,275 @@
+Keyboard mapping
+================
+This release of rdesktop uses a new, portable keyboard mapping
+implementation. It should hopefully work on all X11 systems. This new
+implementation only looks at X11 keysyms: Not on (nonportable)
+keycodes or modifier status. This means that rdesktop will obey your
+local keyboard configuration. For example, if you have swapped
+CapsLock and Control, rdesktop will use this mapping. 
+
+XKB is currently not used. It seems like a good idea to me, but since
+some X servers (like Xvnc) does not support XKB, we still need to use
+the plain old interface as well, at least. 
+
+There are still some small problems.
+
+* CapsLock: CapsLock changes are never sent to the RDP
+  server. rdesktop does not know which keys that are modified by
+  CapsLock and which are not. So, the CapsLock indicator in Wordpad
+  etc will always be off.
+
+Composing/Multi_key is supported. For more information, see:
+
+  MIT:              $SRC/xc/nls/X11/locale/Compose/iso8859-1
+  XFree86:          /usr/X11R6/lib/X11/locale/*/Compose
+  Solaris' Openwin: /usr/openwin/include/X11/Suncompose.h
+                    /usr/openwin/lib/locale/*/Compose
+  Irix6:            compose(5)
+
+
+Keymap files
+============
+The names of the keymaps follows RFC1766. 
+
+(You can find a translation from Windows keyboard layout numbers to
+keymap names by looking at
+HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MIME\Database\RFC1766 in the
+registry.)
+
+
+Contents of keymap files
+========================
+The keymaps are line based. There are four different types of lines:
+
+1) include lines
+Syntax:
+include <another-map-file>
+
+Example:
+include common
+
+
+2) map lines
+Syntax:
+map <hex-number>
+
+Example:
+map 0x41d
+
+Map-lines specifies how the remote RDP server should interpret the
+sent scancodes. 
+
+
+3) Translation lines
+Syntax:
+<keysym-name> <scancode> [flags..]
+
+Example:
+onehalf 0x29 shift
+
+The scancode can be found in scancodes.h. Note: The scancode value for
+extended keys can be calculated by OR:ing with 0x80. Example: The
+Delete key have the scancode sequence 0xe0, 0x52. You can get the
+scancode value to put into the map file by running:
+
+python -c "print hex(0x80 | 0x52)"
+
+If flags are "altgr", "shift", the scancode sent for this keysym will
+be prefixed with AltGr, or Shift.
+
+If flags includes "addupper", a translation for this keysyms uppercase
+name will be added as well, in addition to the non-uppercase
+name. Example:
+
+x 2d addupper
+
+...will add an translation for "X" automatically, just like if you
+would specify:
+
+X 2d shift
+
+If flags include "localstate", the modifier to send will be determined
+by the local modifier state. 
+
+If flags is "inhibit", nothing will be sent to the server. 
+
+If flags is "numlock", rdesktop will make sure that the remote NumLock
+state is on before generating the key event. Otherwise, it will make
+sure NumLock is off.
+
+
+4) enable_compose
+
+If any line starts with the keyword "enable_compose", rdesktop will
+enable local Compose/Multi_key handling. Enabling this will often make
+it impossible to compose characters with dead keys (on the remote
+side). This is because when local compose support is enabled, dead
+keys will not be sent to the remote side. 
+
+
+5) sequence lines
+Syntax:
+sequence <event-keysym-name> <keysym-name1> <keysym-name2> ...
+
+Examples:
+sequence eacute dead_acute e
+sequence F12 f o o at e x a m p l e period c o m
+
+Sequence lines allows you to specify that multiple scancodes should be
+sent to the RDP server, in response to one X11 keyboard event. Note:
+The sequence is sent at the X11 KeyPress event. Nothing is sent at
+KeyRelease.
+
+
+6) keyboard_type lines
+Syntax:
+keyboard_type <hex-number>
+ 
+keyboard_type lines specifies the keyboard type. Default value is 0x4
+(en-us 101/104 keys keyboard).
+
+
+7) keyboard_subtype lines
+Syntax:
+keyboard_subtype <hex-number>
+
+keyboard_subtype lines specifies the keyboard subtype. Default value
+is 0x0 (en-us 101/104 keys keyboard).
+
+
+8) keyboard_functionkeys lines
+Syntax:
+keyboard_functionkeys <hex-number>
+
+keyboard_functionkeys specifies the number of keyboard function
+keys. Default value is 0xc (12, for standard 101/104 keys keyboard).
+
+
+
+
+Suggested X11 keysym mapping on PCs
+===================================
+Unfortunately, there is no standard for which keysyms a given key
+should generate. If you have a PC-keyboard with Windows keys, I suggest this mapping:
+
+Keyboard keys:
+CtrlLeft WinLeft AltLeft Space AltGr WinRight Menu CtrlRight
+
+...should generate keysyms:
+Control_L Super_L Alt_L space Mode_switch Super_R Menu Control_R
+
+Additionally:
+Shift-Alt should produce Meta_L
+Shift-AltGr should produce Multi_Key. 
+
+Use a modifier-map like this:
+
+shift       Shift_L (0x32),  Shift_R (0x3e)
+lock        Caps_Lock (0x25)
+control     Control_L (0x42),  Control_R (0x6d)
+mod1        Alt_L (0x40)
+mod2        Num_Lock (0x4d)
+mod3        Mode_switch (0x71)
+mod4        Super_L (0x73),  Super_R (0x74)
+mod5        Scroll_Lock (0x4e)
+
+
+Updating / writing keymap files
+===============================
+When writing new or updating keymap files, please use comments and
+blanks, to increase readability. The "sv" keymap is a good template. 
+
+When you need to add a translation to a keymap file, do:
+
+    1. Get the "key number" for this key, by looking at keynums.png. 
+
+    2. Take a look at scancodes.h, and look for
+    SCANCODE_KEY_<my-key-number>. The scancode value is at the end of
+    the line. If the line contains (SCANCODE_EXTENDED | 0xsomething),
+    then you should OR 0x80 to this value. For example, you can do:
+    
+    python -c "print hex(0x80 | 0xsomething)"
+
+    3. Put the scancode (from step 2) and keysym name (found in the
+    error message) into the keymap file. 
+
+
+Special keys
+============
+
+* The combination Ctrl-Alt-Enter toggles between fullscreen and
+  non-fullscreen mode. 
+
+* Meta, Hyper and Super are treated as windows keys. RDP4 does not
+  support the windows keys though, so if you are running RDP4, these
+  keys will translate to Ctrl-Esc. 
+
+
+Links
+=====
+http://www.win.tue.nl/~aeb/linux/kbd/scancodes.html
+
+
+Test cases
+==========
+When changing the keyboard code, make sure all these tests in Notepad
+works:
+
+1. Ctrl+f should bring up Find dialog, with CapsLock both on and off. 
+
+2. Ctrl+Shift+arrows should mark text, with CapsLock both on and off. 
+
+3. Test a sequence, like egrave. If you don't have this symbol in your
+   keyboard layout, try something like:
+
+   xmodmap -e "keycode 49 = egrave"
+
+4. Test a char generated with AltGr, such as @ on a swedish keyboard. 
+
+5. Test Ctrl-Alt-Delete. 
+
+6. Ctrl-Alt-Enter should toggle fullscreen. 
+
+7. Test NumLock synchronization using the -N option. Excel is able to
+   indicate the current NumLock state. Verify that the status is
+   updated correctly on reconnects. 
+
+8. Test the Windows keys, standalone as well as in combination with,
+   say, E.
+
+9. Make sure the system menu (via Alt-space) cannot be accessed in
+   single app mode.
+
+10. Make sure keymaps can be loaded from ~/.rdesktop/keymaps,
+    KEYMAP_PATH, $CWD/keymaps, and from an absolute path. 
+
+11. Press Shift, then press a key modified by shift, the release
+    shift, then release the other key.  Do this in a speedy fasion.
+    Make sure the shift state is not stuck down.
+
+12. Test all numpad keys, when not using the -N option. 
+
+13. Map a single, un-shifted key (such as F1) to XK_A:
+    xmodmap -e "keycode 67 = A A"
+
+    Perform in Notepad:
+    * Write some text
+    * Press F1
+    * Press b
+    * Release b
+    * Release F1
+
+    Verify that shift is not stuck down, by clicking on the text. 
+
+14. Use a keyboard layout where Meta_L can be generated with Shift_R +
+    Alt_L. Then:
+
+    * Start Notepad
+    * Press Shift_R
+    * Press Alt_L
+    * Release Shift_R
+    * Release Alt_L
+    * Press "e"
+
+    Verify that you get an "e" in Notepad, rather than start Windows
+    Explorer. 
Index: /trunk/src/VBox/RDP/client-1.8.3/doc/licensing.txt
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/doc/licensing.txt	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/doc/licensing.txt	(revision 55121)
@@ -0,0 +1,56 @@
+
+To be able to connect to Microsoft Windows 2000 Terminal Services (and
+probably later versions), you'll need to deal with licensing. This is
+complicated. This file is supposed to contain some information about
+how rdesktop works with Microsofts license systems.
+
+There's a lot of information on the MS web site, for example,
+http://support.microsoft.com/default.aspx?scid=kb;EN-US;287687.
+
+From the rdesktop mailing list:
+
+Peter Åstrand <astrand@cendio.se>, 2003-02-06
+
+> We are running rdesktop 1.2 on machine A and connects to a Windows 2000
+> Server (machine B). The W2K machine has 5 real licenses installed ("Windows
+> 2000 Terminal Services Client Access License", "Open" type). This can be
+> verifier by using "Terminal Services Licensing". The problem is that all
+> issued licenses have an expire-date. The expire date for the license issued
+> to A was reached today, and no more connections could be made until we
+> changed the client name (by using -n).
+> 
+> We also have another similiar systems, with Linux machine C and W2K server 
+> D. This server has 200 licenses installed of the type "Select". On this 
+> server, the issued licenses seems to be permanent: The expire date is set 
+> to "-", and we have no problem with this system. 
+> 
+> The question of course is why the first system issues license with
+> expiration date, while the second system issues permanent licenses.
+
+
+Darryn Capes-Davis, 2003-02-07
+
+> I have been through the problems and can tell you what is going
+> on. The main difference of Machine B (Server 1) and Machine D (Server
+> 2) is that from what I see Machine B has Service Pack 3 installed and
+> Machine D does not.  You see in Service Pack 3 there was a change made
+> to TS Licencing in that Microsoft introduced a licence recovery
+> mechanism. To cut to the point (I don't know the details) rdesktop 1.2
+> with SAVE_LICENCE defined works fine.  In the new lic method the
+> terminal server expects a valid licence to be presented to renew
+> it. Otherwise it just expires it - and a day later you will see it
+> actually gone (it does housekeeping once a day)! So if SAVE_LICENCE
+> code is not enabled then it just expires and you can't use the licence
+> until it cleans it away - and this is where a little gotcha is - if
+> you move from using an rdesktop without SAVE_LICENCE to one with
+> SAVE_LICENCE then it still won't recover an 'expired' licence. You
+> have to wait for the daily housekeeping to clean it up - this really
+> had me going for half a day or so! This is exactly what happened to
+> you.
+> 
+> The Server pre Spk 3 has the old model where licences never expire. To
+> recover a licence that you never wanted to use again you have to call
+> the Microsoft Clearing House. That's why they introduced the new
+> method. And if you upgrade a Pre Spk3 server to Spk3 then the licences
+> granted still stay with the old method - only new licences granted
+> will use the new expiry method.
Index: /trunk/src/VBox/RDP/client-1.8.3/doc/patches.txt
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/doc/patches.txt	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/doc/patches.txt	(revision 55121)
@@ -0,0 +1,340 @@
+This file documents some of all patches for rdesktop, floating around
+the net, and how they are related to the current (CVS) version of
+rdesktop. Things left to do are marked with TBD (To Be Done). 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/Makefile.diff
+Description:
+Makefile changes which makes it possible to compile rdesktop on SunOS
+and OSF1.
+Status:
+Applied (slightly modified)
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/assar_19-7-2.hostlen.patch
+Description:
+Fix for hostnames longer than 30 chars. 
+Status:
+Applied (revision 1.11 of secure.c) 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/backingstore+privatecolormap-for-19-3-9.patch
+Description:
+This adds support for 1) Private color maps (useful for 8 bpp mode)
+and 2) backingstore selection. 
+Status:
+1) is not needed anymore; rdesktop automatically uses Private color
+map in 8 bpp mode. 2) is, as far as I understand, also not
+need. rdesktop automatically uses a software backing store if the
+Xserver does not provide one. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/ben_xwin.c.diff
+Description:
+Fixes for CapsLock and NumLock. 
+Status:
+Not needed anymore, with the new keyboard mapping implementation. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/ctrl1nohang.diff
+Description:
+Fixes problem with ctrl1 hangs. 
+Status:
+Not needed anymore, with the new keyboard mapping implementation. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/downkeypatch.diff
+Description:
+Seems to keep track of the remote modifier status. 
+Status:
+Not needed anymore, with the new keyboard mapping implementation. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/fasttext2+nobackpixmap.patch
+Description:
+(From http://mail.rdesktop.org/archive/2001/msg00218.html):
+
+1) Added --no-backpixmap option to disable the ugly double drawing in
+xwin.c (I have a very robust backing storage in my X, so I don't need
+it ;)
+
+2) More optimizations to text draw (previous fast-text patch was
+included in 192-3-6-2). In text drawing with solid background the
+glyphs are drawn with stippled fill instead of XCopyPlane (runs faster
+on my S3Trio64 with XFree 3.3.6, please test it on other
+configurations to validate this). The WinTach not show any improvement
+with this change, it seems to use all transparent background text
+draws, but with a old PC Magazine Winbench (3.1) doing the scroll text
+test the speed gain is significative.
+
+3) My Previous patch to disable backing storage in fullscreen
+
+Status:
+1) is not relevant any more, since rdesktop only uses backing store if
+the Xserver does not provide backing store. 
+Need to examine if 2) and 3) are still useful. TBD. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/francisco_fix_patblt.html
+Description:
+The colors in patterns drawn with "pattern blt" order was inverted (fg
+& bg). (See the background of the yellow help banners)
+Status:
+Applied (in revision 1.29, 2002/07/14)
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/frank_1linerfix.html
+Description:
+ui_create_glyph was not called with ipattern. 
+Status:
+Applied (in revision 1.29, 2002/07/14). 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/frank_fasttext.patch.txt
+Description:
+Some kind of performence improvements. 
+Status:
+From what I can tell, this patch is no longer necessary. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/hostname-patch
+Description:
+(From http://mail.rdesktop.org/archive/2001/msg00163.html):
+
+rdesktop uses gethostname to figure out the hostname, but gethostname
+under linux returns an error when the hostname is longer than the
+buffer.  This hack gives gethostname a 64 char buffer and then strips
+the first 16 chars or upto the first '.' and puts the result in
+hostname[16].
+
+Status:
+Applied in version 1.10 of rdesktop.c. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/hove-19-7-2endian.diff
+Description:
+Includes a program for testing endianness. 
+Status:
+rdesktop determines endianness at runtime. This patch is not needed
+anymore. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/mmihalik_19-7-3-keyfix-4.patch
+Description:
+Some kind of new alternative keyboard mapping imlementation. 
+Status:
+Not needed anymore, with the new keyboard mapping implementation. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/norbert_fullscreen.patch
+Description:
+Fullscreen mode. 
+Status:
+Applied. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/norbert_percent.txt
+Description:
+Makes is possible to specify RDP geometry based a percent value of the
+current desktop size. 
+Status:
+Not applied. I don't think many people will need this. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/norbert_rdp_tcp_port.diff
+Description:
+Command line tcp port argument. 
+Status:
+Applied. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/patch19-7-2.xyPos.emptyPassword.patch
+Description:
+This patch adds:
+1) Support for empty passwords
+2) Support for asking for password interactively
+3) Support for +<xoff>+<yoff> geometry. 
+
+Status:
+1) and 2) can be solved by the -P parameter; patch not needed. 
+Functionality for 3) is currently missing. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/rdesktop-1.0.0-19-7-1-mmihalik-3.diff
+Description:
+Defines DO_GLYPH() etc. 
+Status:
+As far as I understand, this patch is applied. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/rdesktop-1.0.0-mmihalik-1.diff
+Description:
+Misc drawing changes. 
+Status:
+As far as I understand, this patch is applied. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/rdesktop-1.0.0-pl19-7-2-mmihalik-1.diff
+Description:
+Some kind of new alternative keyboard mapping implementation. 
+Status:
+Not needed anymore, with the new keyboard mapping implementation. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/rdesktop-gmp.patch
+Description:
+Use GMP for RSA crypto. 
+Status:
+Not needed since rdesktop now use OpenSSL for all of the crypto.
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/rdesktop-new_kb.patch
+Description:
+Modifies one of the old keyboard mapping implementations in some way. 
+Status:
+Not needed anymore, with the new keyboard mapping implementation. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/rdesktop-openssl.patch
+Description:
+Support for linking rdesktop with OpenSSL. 
+Status:
+Not needed anymore, rdesktop can optionally use system 
+OpenSSL. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/rdesktop.vncviewer_patch
+Description:
+Hack for making the old (broken) keyboard mapping implementation work
+with the VNC Xserver. 
+Status:
+Not needed anymore, with the new keyboard mapping implementation. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/rdesktop_keymap.patch
+Description:
+Some kind of new alternative keyboard mapping implementation. 
+Status:
+Not needed anymore, with the new keyboard mapping implementation. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/rdp-srvr-19-6-6.diff
+Description:
+Basic RDP server. 
+Status:
+Not applied. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/scroll-to-death-patch.txt
+Description:
+Fixes scroll-to-death problem in Excel and other applications. 
+Status:
+Not needed; fixed in another way in recent versions of rdesktop. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/spark-manpage-patch-19.4
+Description:
+Adds a manual page. 
+Status:
+Not needed; rdesktop contains a manual page now. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/spark-manpage-patch-19.4-1
+Description:
+Adds a manual page. 
+Status:
+Not needed; rdesktop contains a manual page now. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/spark_xinerama-patch2
+Description:
+Adds XINERAMA support to rdesktop. 
+Status:
+Not applied yet. TBD. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/svenni_dis_wmkeybnds.patch
+Description:
+Commandline flag to disable keyboard grabbing. 
+Status:
+Applied. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/svenni_disable_bs_in_x-tiny-patch
+Description:
+Disables backing store for TinyX. 
+Status:
+As far as I understand, this patch is not need any longer. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/vincent_19-7-2.license.patch
+Description:
+TBD
+Status:
+Not yet examined. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/vincent_19-7-2.secure.patch
+Description:
+Fixes a problem during the connection to a French NT4 TSE (a French
+NT4 TSE doesn't use encryptation).
+Status:
+Applied. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/vincent_19-7-3_excel.patch
+Description:
+Makes matrixes appear better, such as those found in Excel/toad etc.
+Status:
+Applied. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/vincent_8bpp.patch
+Description:
+Support a 8bpp display (256 colours). 
+Status:
+An enhanced version is included in rdesktop; this patch is not needed any more. 
+
+
+URL:
+http://bibl4.oru.se/projects/rdesktop/patch19/patches/vpypatch.txt
+Description:
+Various changes for one of the old keyboard stuff. 
+Status:
+Not needed anymore, with the new keyboard mapping implementation. 
Index: /trunk/src/VBox/RDP/client-1.8.3/doc/rdesktop.1
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/doc/rdesktop.1	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/doc/rdesktop.1	(revision 55121)
@@ -0,0 +1,338 @@
+.TH rdesktop 1 "November 2005"
+.SH NAME
+.I rdesktop
+\- Remote Desktop Protocol client
+.SH SYNOPSIS
+.B rdesktop [options] server[:port]
+.br
+.SH DESCRIPTION
+.I rdesktop
+is a client for Remote Desktop Protocol (RDP), used in a number of Microsoft
+products including Windows NT Terminal Server, Windows 2000 Server, Windows XP
+and Windows 2003 Server.
+
+.SH OPTIONS
+.TP
+.BR "-u <username>"
+Username for authentication on the server.
+.TP
+.BR "-d <domain>"
+Domain for authentication.
+.TP
+.BR "-s <shell>"
+Startup shell for the user - starts a specific application instead of Explore.
+If SeamlessRDP is enabled this is the application which i started in seamless mode.
+.TP
+.BR "-c <directory>"
+The initial working directory for the user.  Often used in combination with -s
+to set up a fixed login environment.
+.TP
+.BR "-p <password>"
+The password to authenticate with.  Note that this may have no effect if
+"Always prompt for password" is enabled on the server.  WARNING: if you specify
+a password on the command line it may be visible to other users when they use
+tools like ps.  Use -p - to make rdesktop request a password at startup (from
+standard input).
+.TP
+.BR "-n <hostname>"
+Client hostname.  Normally rdesktop automatically obtains the hostname of the
+client.
+.TP
+.BR "-k <keyboard-map>"
+Keyboard layout to emulate.  This requires a corresponding keymap file to be
+installed.  The standard keymaps provided with rdesktop follow the RFC1766
+naming scheme: a language code followed by a country code if necessary - e.g.
+en-us, en-gb, de, fr, sv, etc.
+
+The default keyboard map depends on the current locale (LC_* and LANG
+environment variables). If the current locale is unknown, the default
+keyboard map is en-us (a US English keyboard).
+
+The keyboard maps are file names, which means that they are case
+sensitive. The standard keymaps are all in lowercase.
+
+The keyboard maps are searched relative to the directories
+$HOME/.rdesktop/keymaps, KEYMAP_PATH (specified at build time), and
+$CWD/keymaps, in this order. The keyboard-map argument can also be an
+absolute filename.
+
+The special value `none' can be used instead of a keyboard map.
+In this case, rdesktop will guess the scancodes from the X11 event key
+codes using an internal mapping method. This method only supports the
+basic alphanumeric keys and may not work properly on all platforms
+so its use is discouraged.
+.TP
+.BR "-g <geometry>"
+Desktop geometry (WxH). If geometry is the special word "workarea", the geometry
+will be fetched from the extended window manager hints property _NET_WORKAREA, from
+the root window. The geometry can also be specified as a percentage of the whole
+screen, e.g. "-g 80%". 
+
+If the specified geometry depends on the screen size, and the screen
+size is changed, rdesktop will automatically reconnect using the new
+screen size. This requires that rdesktop has been compiled with RandR
+support.
+.TP
+.BR "-i"
+Use password as smartcard pin. If a valid user certificate is matched in smart card
+reader the password passed with \f-p\fR argument is used as pin for the smart card.
+This feature also requires that smart card redirection is used using \f-r scard\fR argument.
+.TP
+.BR "-f"
+Enable fullscreen mode.  This overrides the window manager and causes the
+rdesktop window to fully cover the current screen.  Fullscreen mode can be
+toggled at any time using Ctrl-Alt-Enter.
+.TP
+.BR "-b"
+Force the server to send screen updates as bitmaps rather than using
+higher-level drawing operations.
+.TP
+.BR "-t"
+Disable use of remote control. This will disable features like seamless connection
+sharing.
+.TP
+.BR "-A <seamlessrdpshell>"
+Enable SeamlessRDP by specifying the path to seamless rdp shell. 
+In this mode, rdesktop creates a X11 window for each window on the server side. 
+This mode requires the SeamlessRDP server side component, which is available from 
+\fIhttp://www.cendio.com/seamlessrdp/\fR.
+
+When using this option, you should normally specify a startup shell which
+launches the desired application through SeamlessRDP. 
+
+Example: rdesktop -A 'c:\\seamlessrdp\\seamlessrdpshell.exe' -s 'notepad' mywts.domain.com
+
+Any subsequential call to the above commandline example will make use of the seamless 
+connection sharing feature which spawns another notepad in the current connection to the
+specified server and then exit.
+
+.TP
+.BR "-B"
+Use the BackingStore of the Xserver instead of the integrated one in
+rdesktop.
+.TP
+.BR "-e"
+Disable encryption.  This option is only needed (and will only work) if you
+have a French version of NT TSE.
+.TP
+.BR "-E"
+Disable encryption from client to server.  This sends an encrypted login packet,
+but everything after this is unencrypted (including interactive logins).
+.TP
+.BR "-m"
+Do not send mouse motion events.  This saves bandwidth, although some Windows
+applications may rely on receiving mouse motion.
+.TP
+.BR "-C"
+Use private colourmap.  This will improve colour accuracy on an 8-bit display,
+but rdesktop will appear in false colour when not focused.
+.TP
+.BR "-D"
+Hide window manager decorations, by using MWM hints. 
+.TP
+.BR "-K"
+Do not override window manager key bindings.  By default rdesktop attempts
+to grab all keyboard input when it is in focus.
+.TP
+.BR "-S <button size>"
+Enable single application mode. This option can be used when running a
+single, maximized application (via -s). When the minimize button of
+the windows application is pressed, the rdesktop window is minimized
+instead of the remote application. The maximize/restore button is
+disabled. For this to work, you must specify the correct button
+size, in pixels. The special word "standard" means 18 pixels. 
+.TP
+.BR "-T <title>"
+Sets the window title. The title must be specified using an UTF-8 string. 
+.TP
+.BR "-N"
+Enable numlock syncronization between the Xserver and the remote RDP
+session.  This is useful with applications that looks at the numlock
+state, but might cause problems with some Xservers like Xvnc. 
+.TP
+.BR "-X <windowid>"
+Embed rdesktop-window in another window. The windowid is expected to
+be decimal or hexadecimal (prefixed by 0x).
+.TP
+.BR "-a <bpp>"
+Sets the colour depth for the connection (8, 15, 16, 24 or 32).
+More than 8 bpp are only supported when connecting to Windows XP
+(up to 16 bpp) or newer.  Note that the colour depth may also be
+limited by the server configuration. The default value is the depth 
+of the root window. 
+.TP
+.BR "-z"
+Enable compression of the RDP datastream.
+.TP
+.BR "-x <experience>"
+Changes default bandwidth performance behaviour for RDP5. By default only
+theming is enabled, and all other options are disabled (corresponding
+to modem (56 Kbps)). Setting experience to b[roadband] enables menu
+animations and full window dragging. Setting experience to l[an] will
+also enable the desktop wallpaper. Setting experience to m[odem]
+disables all (including themes). Experience can also be a hexidecimal
+number containing the flags.
+.TP
+.BR "-P"
+Enable caching of bitmaps to disk (persistent bitmap caching). This generally
+improves performance (especially on low bandwidth connections) and reduces
+network traffic at the cost of slightly longer startup and some disk space.
+(10MB for 8-bit colour, 20MB for 15/16-bit colour, 30MB for 24-bit colour
+and 40MB for 32-bit colour sessions)
+.TP
+.BR "-r <device>"
+Enable redirection of the specified device on the client, such
+that it appears on the server. Note that the allowed
+redirections may be restricted by the server configuration.
+
+Following devices are currently supported:
+.TP
+.BR "-r comport:<comport>=<device>,..."
+Redirects serial devices on your client to the
+server. Note that if you need to change any settings on the serial device(s),
+do so with an appropriate tool before starting rdesktop. In most
+OSes you would use stty. Bidirectional/Read support requires Windows XP or newer.
+In Windows 2000 it will create a port, but it's not seamless, most
+shell programs will not work with it.
+.TP
+.BR "-r disk:<sharename>=<path>,..."
+Redirects a path to the share \\\\tsclient\\<sharename> on the server
+(requires Windows XP or newer). The share name is limited to 8
+characters. 
+.TP
+.BR "-r lptport:<lptport>=<device>,..."
+Redirects parallel devices on your client to the server.
+Bidirectional/Read support requires Windows XP or newer. In Windows 2000
+it will create a port, but it's not seamless, most shell programs will not work with
+it.
+.TP
+.BR "-r printer:<printername>[=<driver>],..."
+Redirects a printer queue on the client to the server. The <printername>
+is the name of the queue in your local system. <driver> defaults to a
+simple PS-driver unless you specify one. Keep in mind that you need a
+100% match in the server environment, or the driver will fail. The first
+printer on the command line will be set as your default printer.
+.TP
+.BR "-r sound:[local|off|remote]"
+Redirects sound generated on the server to the client. "remote" only has
+any effect when you connect to the console with the -0 option. (Requires
+Windows XP or newer).
+.TP
+.BR "-r lspci"
+Activates the lspci channel, which allows the server to enumerate the
+clients PCI devices. See the file lspci-channel.txt in the
+documentation for more information.
+.TP
+.BR "-r scard[:<Scard Name>=<Alias Name>[;<Vendor Name>][,...]]"
+Enables redirection of one or more smart-cards. You can provide
+static name binding between linux and windows. To do this you
+can use optional parameters as described: <Scard Name> - device name in
+Linux/Unix enviroment, <Alias Name> - device name shown in Windows enviroment
+<Vendor Name> - optional device vendor name. For list of examples run
+rdesktop without parameters.
+.TP
+.BR "-0"
+Attach to the console of the server (requires Windows Server 2003
+or newer).
+.TP
+.BR "-4"
+Use RDP version 4.
+.TP
+.BR "-5"
+Use RDP version 5 (default).
+.PP
+
+.SH "CredSSP Smartcard options"
+.TP
+.BR "--sc-csp-name <name>"
+Specify the CSP (Crypto Service Provider) to use on the windows side for the smartcard
+authentication. CSP is the driver for your smartcard and it seems like this is required
+to be specified for CredSSP authentication. For swedish NetID the following CSP name is
+used; "Net iD - CSP".
+.TP
+.BR "--sc-container-name <name>"
+Specify the container name, usally this is the username for default container and it seems
+like this is required to be specified for CredSSP authentication.
+.TP
+.BR "--sc-reader-name <name>"
+Specify the reader name to be used to prevent the pin code being sent to wrong card if there
+are several readers.
+.TP
+.BR "--sc-card-name <name>"
+Specify the card name for example; "Telia EID IP5a".
+.PP
+
+.SH "EXIT VALUES"
+.PP 
+.IP "\fB0\fP"
+RDP session terminated normally
+.IP "\fB1\fP"
+Server initiated disconnect (also returned for logoff by XP joined to a domain)
+.IP "\fB2\fP"
+Server initiated logoff
+.IP "\fB3\fP"
+Server idle timeout reached
+.IP "\fB4\fP"
+Server logon timeout reached
+.IP "\fB5\fP"
+The session was replaced
+.IP "\fB6\fP"
+The server is out of memory
+.IP "\fB7\fP"
+The server denied the connection
+.IP "\fB8\fP"
+The server denied the connection for security reason
+.IP "\fB9\fP"
+The user cannot connect to the server due to insufficient access
+privileges
+.IP "\fB10\fP"
+The server does not accept saved user credentials and requires that
+the user enter their credentials for each connection
+.IP "\fB11\fP"
+Disconnect initiated by administration tool
+.IP "\fB12\fP"
+Disconnect initiated by user
+.IP "\fB16\fP"
+Internal licensing error
+.IP "\fB17\fP"
+No license server available
+.IP "\fB18\fP"
+No valid license available
+.IP "\fB19\fP"
+Invalid licensing message
+.IP "\fB20\fP"
+Hardware id doesn't match software license
+.IP "\fB21\fP"
+Client license error
+.IP "\fB22\fP"
+Network error during licensing protocol
+.IP "\fB23\fP"
+Licensing protocol was not completed
+.IP "\fB24\fP"
+Incorrect client license enryption
+.IP "\fB25\fP"
+Can't upgrade license
+.IP "\fB26\fP"
+The server is not licensed to accept remote connections
+.IP "\fB62\fP"
+The local client window was closed
+.IP "\fB63\fP"
+Some other, unknown error occured
+.IP "\fB64\fP"
+Command line usage error
+.IP "\fB69\fP"
+A service or resource (such as memory) is unavailable
+.IP "\fB70\fP"
+An internal software error has been detected
+.IP "\fB71\fP"
+Operating system error
+.IP "\fB76\fP"
+Protocol error or unable to connect to remote host.
+
+.PP 
+.SH LINKS
+Main website of rdesktop
+.br
+\fIhttp://www.rdesktop.org/
+.LP
+.PP
Index: /trunk/src/VBox/RDP/client-1.8.3/doc/redirection.txt
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/doc/redirection.txt	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/doc/redirection.txt	(revision 55121)
@@ -0,0 +1,74 @@
+
+Syntax for configuring RDP redirection modules
+==============================================
+
+General
+-------
+
+All redirection is configured using the -r option. The general syntax
+is:
+
+-r <module>:<string>
+
+<module> is the name of the redirection module. The following names
+are valid: disk, printer, lptport, comport, clipboard, sound. 
+
+<string> is interpreted by each redirection module. 
+
+The redirection modules are described below.
+
+
+disk mapping
+-------------
+Multiple mappings possible: yes
+Default: no disk redirected
+Syntax: -r disk:<sharename>=<path>
+Example: -r disk:home=/home/johndoe
+
+
+printer mapping
+---------------
+Multiple mappings possible: yes
+Default: no printers redirected
+Syntax: -r printer:<printername>
+Example: -r printer:mydeskjet
+
+
+
+LPT port mapping
+----------------
+Multiple mappings possible: yes
+Default: no LPT ports redirected
+Syntax: -r lptport:<lptport>=<device>
+Example: -r lptport:LPT1=/dev/lp0
+
+
+COM port mapping
+----------------
+Multiple mappings possible: yes
+Default: no COM ports redirected
+Syntax: -r comport:<comport>=<device>
+Example: -r comport:COM1=/dev/ttyS0
+
+
+clipboard mapping
+-----------------
+Multiple mappings possible: no
+Default: yes
+Syntax: -r clipboard:[yes|no]
+Example: -r clipboard:no
+
+
+sound mapping
+-------------
+Multiple mappings possible: no
+Default: off
+Syntax: -r sound:[local|off|remote]
+
+"local" means "Bring to this computer"
+"off" means "Do not play"
+"remote" means "Leave at remote computer"
+
+Example: -r sound:remote
+
+
Index: /trunk/src/VBox/RDP/client-1.8.3/ewmhints.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/ewmhints.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/ewmhints.c	(revision 55121)
@@ -0,0 +1,611 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+
+   Support functions for Extended Window Manager Hints,
+   http://www.freedesktop.org/wiki/Standards_2fwm_2dspec
+
+   Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+   Copyright 2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#include "rdesktop.h"
+
+#define _NET_WM_STATE_REMOVE        0	/* remove/unset property */
+#define _NET_WM_STATE_ADD           1	/* add/set property */
+#define _NET_WM_STATE_TOGGLE        2	/* toggle property  */
+
+extern Display *g_display;
+
+static Atom g_net_wm_state_maximized_vert_atom, g_net_wm_state_maximized_horz_atom,
+	g_net_wm_state_hidden_atom, g_net_wm_name_atom, g_utf8_string_atom,
+	g_net_wm_state_skip_taskbar_atom, g_net_wm_state_skip_pager_atom,
+	g_net_wm_state_modal_atom, g_net_wm_icon_atom, g_net_wm_state_above_atom;
+
+Atom g_net_wm_state_atom, g_net_wm_desktop_atom;
+
+/* 
+   Get window property value (32 bit format) 
+   Returns zero on success, -1 on error
+*/
+static int
+get_property_value(Window wnd, char *propname, long max_length,
+		   unsigned long *nitems_return, unsigned char **prop_return, int nowarn)
+{
+	int result;
+	Atom property;
+	Atom actual_type_return;
+	int actual_format_return;
+	unsigned long bytes_after_return;
+
+	property = XInternAtom(g_display, propname, True);
+	if (property == None)
+	{
+		fprintf(stderr, "Atom %s does not exist\n", propname);
+		return (-1);
+	}
+
+	result = XGetWindowProperty(g_display, wnd, property, 0,	/* long_offset */
+				    max_length,	/* long_length */
+				    False,	/* delete */
+				    AnyPropertyType,	/* req_type */
+				    &actual_type_return,
+				    &actual_format_return,
+				    nitems_return, &bytes_after_return, prop_return);
+
+	if (result != Success)
+	{
+		fprintf(stderr, "XGetWindowProperty failed\n");
+		return (-1);
+	}
+
+	if (actual_type_return == None || actual_format_return == 0)
+	{
+		if (!nowarn)
+			fprintf(stderr, "Window is missing property %s\n", propname);
+		return (-1);
+	}
+
+	if (bytes_after_return)
+	{
+		fprintf(stderr, "%s is too big for me\n", propname);
+		return (-1);
+	}
+
+	if (actual_format_return != 32)
+	{
+		fprintf(stderr, "%s has bad format\n", propname);
+		return (-1);
+	}
+
+	return (0);
+}
+
+/* 
+   Get current desktop number
+   Returns -1 on error
+*/
+static int
+get_current_desktop(void)
+{
+	unsigned long nitems_return;
+	unsigned char *prop_return;
+	int current_desktop;
+
+	if (get_property_value
+	    (DefaultRootWindow(g_display), "_NET_CURRENT_DESKTOP", 1, &nitems_return,
+	     &prop_return, 0) < 0)
+		return (-1);
+
+	if (nitems_return != 1)
+	{
+		fprintf(stderr, "_NET_CURRENT_DESKTOP has bad length\n");
+		return (-1);
+	}
+
+	current_desktop = *prop_return;
+	XFree(prop_return);
+	return current_desktop;
+}
+
+/*
+  Get workarea geometry
+  Returns zero on success, -1 on error
+ */
+
+int
+get_current_workarea(uint32 * x, uint32 * y, uint32 * width, uint32 * height)
+{
+	int current_desktop;
+	unsigned long nitems_return;
+	unsigned char *prop_return;
+	long *return_words;
+	const uint32 net_workarea_x_offset = 0;
+	const uint32 net_workarea_y_offset = 1;
+	const uint32 net_workarea_width_offset = 2;
+	const uint32 net_workarea_height_offset = 3;
+	const uint32 max_prop_length = 32 * 4;	/* Max 32 desktops */
+
+	if (get_property_value
+	    (DefaultRootWindow(g_display), "_NET_WORKAREA", max_prop_length, &nitems_return,
+	     &prop_return, 0) < 0)
+		return (-1);
+
+	if (nitems_return % 4)
+	{
+		fprintf(stderr, "_NET_WORKAREA has odd length\n");
+		return (-1);
+	}
+
+	current_desktop = get_current_desktop();
+
+	if (current_desktop < 0)
+		return -1;
+
+	return_words = (long *) prop_return;
+
+	*x = return_words[current_desktop * 4 + net_workarea_x_offset];
+	*y = return_words[current_desktop * 4 + net_workarea_y_offset];
+	*width = return_words[current_desktop * 4 + net_workarea_width_offset];
+	*height = return_words[current_desktop * 4 + net_workarea_height_offset];
+
+	XFree(prop_return);
+
+	return (0);
+
+}
+
+
+
+void
+ewmh_init()
+{
+	/* FIXME: Use XInternAtoms */
+	g_net_wm_state_maximized_vert_atom =
+		XInternAtom(g_display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
+	g_net_wm_state_maximized_horz_atom =
+		XInternAtom(g_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
+	g_net_wm_state_hidden_atom = XInternAtom(g_display, "_NET_WM_STATE_HIDDEN", False);
+	g_net_wm_state_skip_taskbar_atom =
+		XInternAtom(g_display, "_NET_WM_STATE_SKIP_TASKBAR", False);
+	g_net_wm_state_skip_pager_atom = XInternAtom(g_display, "_NET_WM_STATE_SKIP_PAGER", False);
+	g_net_wm_state_modal_atom = XInternAtom(g_display, "_NET_WM_STATE_MODAL", False);
+	g_net_wm_state_above_atom = XInternAtom(g_display, "_NET_WM_STATE_ABOVE", False);
+	g_net_wm_state_atom = XInternAtom(g_display, "_NET_WM_STATE", False);
+	g_net_wm_desktop_atom = XInternAtom(g_display, "_NET_WM_DESKTOP", False);
+	g_net_wm_name_atom = XInternAtom(g_display, "_NET_WM_NAME", False);
+	g_net_wm_icon_atom = XInternAtom(g_display, "_NET_WM_ICON", False);
+	g_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);
+}
+
+
+/* 
+   Get the window state: normal/minimized/maximized. 
+*/
+#ifndef MAKE_PROTO
+int
+ewmh_get_window_state(Window w)
+{
+	unsigned long nitems_return;
+	unsigned char *prop_return;
+	unsigned long *return_words;
+	unsigned long item;
+	RD_BOOL maximized_vert, maximized_horz, hidden;
+
+	maximized_vert = maximized_horz = hidden = False;
+
+	if (get_property_value(w, "_NET_WM_STATE", 64, &nitems_return, &prop_return, 0) < 0)
+		return SEAMLESSRDP_NORMAL;
+
+	return_words = (unsigned long *) prop_return;
+
+	for (item = 0; item < nitems_return; item++)
+	{
+		if (return_words[item] == g_net_wm_state_maximized_vert_atom)
+			maximized_vert = True;
+		if (return_words[item] == g_net_wm_state_maximized_horz_atom)
+			maximized_horz = True;
+		if (return_words[item] == g_net_wm_state_hidden_atom)
+			hidden = True;
+	}
+
+	XFree(prop_return);
+
+	/* In EWMH, HIDDEN overrides MAXIMIZED_VERT/MAXIMIZED_HORZ */
+	if (hidden)
+		return SEAMLESSRDP_MINIMIZED;
+	else if (maximized_vert && maximized_horz)
+		return SEAMLESSRDP_MAXIMIZED;
+	else
+		return SEAMLESSRDP_NORMAL;
+}
+
+static int
+ewmh_modify_state(Window wnd, int add, Atom atom1, Atom atom2)
+{
+	Status status;
+	XEvent xevent;
+
+	int result;
+	unsigned long nitems;
+	unsigned char *props;
+	uint32 state = WithdrawnState;
+
+	/* The spec states that the window manager must respect any
+	   _NET_WM_STATE attributes on a withdrawn window. In order words, we
+	   modify the attributes directly for withdrawn windows and ask the WM
+	   to do it for active windows. */
+	result = get_property_value(wnd, "WM_STATE", 64, &nitems, &props, 1);
+	if ((result >= 0) && nitems)
+	{
+		state = *(uint32 *) props;
+		XFree(props);
+	}
+
+	if (state == WithdrawnState)
+	{
+		if (add)
+		{
+			Atom atoms[2];
+
+			atoms[0] = atom1;
+			nitems = 1;
+			if (atom2)
+			{
+				atoms[1] = atom2;
+				nitems = 2;
+			}
+
+			XChangeProperty(g_display, wnd, g_net_wm_state_atom, XA_ATOM,
+					32, PropModeAppend, (unsigned char *) atoms, nitems);
+		}
+		else
+		{
+			Atom *atoms;
+			int i;
+
+			if (get_property_value(wnd, "_NET_WM_STATE", 64, &nitems, &props, 1) < 0)
+				return 0;
+
+			atoms = (Atom *) props;
+
+			for (i = 0; i < nitems; i++)
+			{
+				if ((atoms[i] == atom1) || (atom2 && (atoms[i] == atom2)))
+				{
+					if (i != (nitems - 1))
+						memmove(&atoms[i], &atoms[i + 1],
+							sizeof(Atom) * (nitems - i - 1));
+					nitems--;
+					i--;
+				}
+			}
+
+			XChangeProperty(g_display, wnd, g_net_wm_state_atom, XA_ATOM,
+					32, PropModeReplace, (unsigned char *) atoms, nitems);
+
+			XFree(props);
+		}
+
+		return 0;
+	}
+
+	xevent.type = ClientMessage;
+	xevent.xclient.window = wnd;
+	xevent.xclient.message_type = g_net_wm_state_atom;
+	xevent.xclient.format = 32;
+	if (add)
+		xevent.xclient.data.l[0] = _NET_WM_STATE_ADD;
+	else
+		xevent.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
+	xevent.xclient.data.l[1] = atom1;
+	xevent.xclient.data.l[2] = atom2;
+	xevent.xclient.data.l[3] = 0;
+	xevent.xclient.data.l[4] = 0;
+	status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
+			    SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
+	if (!status)
+		return -1;
+
+	return 0;
+}
+
+/* 
+   Set the window state: normal/minimized/maximized. 
+   Returns -1 on failure. 
+*/
+int
+ewmh_change_state(Window wnd, int state)
+{
+	/*
+	 * Deal with the max atoms
+	 */
+	if (state == SEAMLESSRDP_MAXIMIZED)
+	{
+		if (ewmh_modify_state
+		    (wnd, 1, g_net_wm_state_maximized_vert_atom,
+		     g_net_wm_state_maximized_horz_atom) < 0)
+			return -1;
+	}
+	else
+	{
+		if (ewmh_modify_state
+		    (wnd, 0, g_net_wm_state_maximized_vert_atom,
+		     g_net_wm_state_maximized_horz_atom) < 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+
+int
+ewmh_get_window_desktop(Window wnd)
+{
+	unsigned long nitems_return;
+	unsigned char *prop_return;
+	int desktop;
+
+	if (get_property_value(wnd, "_NET_WM_DESKTOP", 1, &nitems_return, &prop_return, 0) < 0)
+		return (-1);
+
+	if (nitems_return != 1)
+	{
+		fprintf(stderr, "_NET_WM_DESKTOP has bad length\n");
+		return (-1);
+	}
+
+	desktop = *prop_return;
+	XFree(prop_return);
+	return desktop;
+}
+
+
+int
+ewmh_move_to_desktop(Window wnd, unsigned int desktop)
+{
+	Status status;
+	XEvent xevent;
+
+	xevent.type = ClientMessage;
+	xevent.xclient.window = wnd;
+	xevent.xclient.message_type = g_net_wm_desktop_atom;
+	xevent.xclient.format = 32;
+	xevent.xclient.data.l[0] = desktop;
+	xevent.xclient.data.l[1] = 0;
+	xevent.xclient.data.l[2] = 0;
+	xevent.xclient.data.l[3] = 0;
+	xevent.xclient.data.l[4] = 0;
+	status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
+			    SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
+	if (!status)
+		return -1;
+
+	return 0;
+}
+
+void
+ewmh_set_wm_name(Window wnd, const char *title)
+{
+	int len;
+
+	len = strlen(title);
+	XChangeProperty(g_display, wnd, g_net_wm_name_atom, g_utf8_string_atom,
+			8, PropModeReplace, (unsigned char *) title, len);
+}
+
+
+int
+ewmh_set_window_popup(Window wnd)
+{
+	if (ewmh_modify_state
+	    (wnd, 1, g_net_wm_state_skip_taskbar_atom, g_net_wm_state_skip_pager_atom) < 0)
+		return -1;
+	return 0;
+}
+
+int
+ewmh_set_window_modal(Window wnd)
+{
+	if (ewmh_modify_state(wnd, 1, g_net_wm_state_modal_atom, 0) < 0)
+		return -1;
+	return 0;
+}
+
+void
+ewmh_set_icon(Window wnd, int width, int height, const char *rgba_data)
+{
+	unsigned long nitems, i;
+	unsigned char *props;
+	unsigned long *cur_set, *new_set;
+	unsigned long *icon;
+
+	cur_set = NULL;
+	new_set = NULL;
+
+	if (get_property_value(wnd, "_NET_WM_ICON", 10000, &nitems, &props, 1) >= 0)
+	{
+		cur_set = (unsigned long *) props;
+
+		for (i = 0; i < nitems;)
+		{
+			if (cur_set[i] == width && cur_set[i + 1] == height)
+				break;
+
+			i += 2 + cur_set[i] * cur_set[i + 1];
+		}
+
+		if (i != nitems)
+			icon = cur_set + i;
+		else
+		{
+			new_set = xmalloc((nitems + width * height + 2) * sizeof(unsigned long));
+			memcpy(new_set, cur_set, nitems * sizeof(unsigned long));
+			icon = new_set + nitems;
+			nitems += width * height + 2;
+		}
+	}
+	else
+	{
+		new_set = xmalloc((width * height + 2) * sizeof(unsigned long));
+		icon = new_set;
+		nitems = width * height + 2;
+	}
+
+	icon[0] = width;
+	icon[1] = height;
+
+	/* Convert RGBA -> ARGB */
+	for (i = 0; i < width * height; i++)
+	{
+		icon[i + 2] =
+			rgba_data[i * 4 + 3] << 24 |
+			((rgba_data[i * 4 + 0] << 16) & 0x00FF0000) |
+			((rgba_data[i * 4 + 1] << 8) & 0x0000FF00) |
+			((rgba_data[i * 4 + 2] << 0) & 0x000000FF);
+	}
+
+	XChangeProperty(g_display, wnd, g_net_wm_icon_atom, XA_CARDINAL, 32,
+			PropModeReplace, (unsigned char *) (new_set ? new_set : cur_set), nitems);
+
+	if (cur_set)
+		XFree(cur_set);
+	if (new_set)
+		xfree(new_set);
+}
+
+void
+ewmh_del_icon(Window wnd, int width, int height)
+{
+	unsigned long nitems, i, icon_size;
+	unsigned char *props;
+	unsigned long *cur_set, *new_set;
+
+	cur_set = NULL;
+	new_set = NULL;
+
+	if (get_property_value(wnd, "_NET_WM_ICON", 10000, &nitems, &props, 1) < 0)
+		return;
+
+	cur_set = (unsigned long *) props;
+
+	for (i = 0; i < nitems;)
+	{
+		if (cur_set[i] == width && cur_set[i + 1] == height)
+			break;
+
+		i += 2 + cur_set[i] * cur_set[i + 1];
+	}
+
+	if (i == nitems)
+		goto out;
+
+	icon_size = width * height + 2;
+	new_set = xmalloc((nitems - icon_size) * sizeof(unsigned long));
+
+	if (i != 0)
+		memcpy(new_set, cur_set, i * sizeof(unsigned long));
+	if (i != nitems - icon_size)
+		memcpy(new_set + i, cur_set + i + icon_size,
+		       (nitems - (i + icon_size)) * sizeof(unsigned long));
+
+	nitems -= icon_size;
+
+	XChangeProperty(g_display, wnd, g_net_wm_icon_atom, XA_CARDINAL, 32,
+			PropModeReplace, (unsigned char *) new_set, nitems);
+
+	xfree(new_set);
+
+      out:
+	XFree(cur_set);
+}
+
+int
+ewmh_set_window_above(Window wnd)
+{
+	if (ewmh_modify_state(wnd, 1, g_net_wm_state_above_atom, 0) < 0)
+		return -1;
+	return 0;
+}
+
+RD_BOOL
+ewmh_is_window_above(Window w)
+{
+	unsigned long nitems_return;
+	unsigned char *prop_return;
+	unsigned long *return_words;
+	unsigned long item;
+	RD_BOOL above;
+
+	above = False;
+
+	if (get_property_value(w, "_NET_WM_STATE", 64, &nitems_return, &prop_return, 0) < 0)
+		return False;
+
+	return_words = (unsigned long *) prop_return;
+
+	for (item = 0; item < nitems_return; item++)
+	{
+		if (return_words[item] == g_net_wm_state_above_atom)
+			above = True;
+	}
+
+	XFree(prop_return);
+
+	return above;
+}
+
+#endif /* MAKE_PROTO */
+
+
+#if 0
+
+/* FIXME: _NET_MOVERESIZE_WINDOW is for pagers, not for
+   applications. We should implement _NET_WM_MOVERESIZE instead */
+
+int
+ewmh_net_moveresize_window(Window wnd, int x, int y, int width, int height)
+{
+	Status status;
+	XEvent xevent;
+	Atom moveresize;
+
+	moveresize = XInternAtom(g_display, "_NET_MOVERESIZE_WINDOW", False);
+	if (!moveresize)
+	{
+		return -1;
+	}
+
+	xevent.type = ClientMessage;
+	xevent.xclient.window = wnd;
+	xevent.xclient.message_type = moveresize;
+	xevent.xclient.format = 32;
+	xevent.xclient.data.l[0] = StaticGravity | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11);
+	xevent.xclient.data.l[1] = x;
+	xevent.xclient.data.l[2] = y;
+	xevent.xclient.data.l[3] = width;
+	xevent.xclient.data.l[4] = height;
+
+	status = XSendEvent(g_display, DefaultRootWindow(g_display), False,
+			    SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
+	if (!status)
+		return -1;
+	return 0;
+}
+
+#endif
Index: /trunk/src/VBox/RDP/client-1.8.3/install-sh
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/install-sh	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/install-sh	(revision 55121)
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	:
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+		chmodcmd=""
+	else
+		instcmd=$mkdirprog
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f "$src" ] || [ -d "$src" ]
+	then
+		:
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		:
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		:
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+	'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		:
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		:
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
Index: /trunk/src/VBox/RDP/client-1.8.3/iso.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/iso.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/iso.c	(revision 55121)
@@ -0,0 +1,369 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - ISO layer
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+   Copyright 2012 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+
+extern RD_BOOL g_encryption;
+extern RD_BOOL g_encryption_initial;
+extern RDP_VERSION g_rdp_version;
+extern RD_BOOL g_use_password_as_pin;
+
+static RD_BOOL g_negotiate_rdp_protocol = True;
+
+extern char *g_sc_csp_name;
+extern char *g_sc_reader_name;
+extern char *g_sc_card_name;
+extern char *g_sc_container_name;
+
+
+/* Send a self-contained ISO PDU */
+static void
+iso_send_msg(uint8 code)
+{
+	STREAM s;
+
+	s = tcp_init(11);
+
+	out_uint8(s, 3);	/* version */
+	out_uint8(s, 0);	/* reserved */
+	out_uint16_be(s, 11);	/* length */
+
+	out_uint8(s, 6);	/* hdrlen */
+	out_uint8(s, code);
+	out_uint16(s, 0);	/* dst_ref */
+	out_uint16(s, 0);	/* src_ref */
+	out_uint8(s, 0);	/* class */
+
+	s_mark_end(s);
+	tcp_send(s);
+}
+
+static void
+iso_send_connection_request(char *username, uint32 neg_proto)
+{
+	STREAM s;
+	int length = 30 + strlen(username);
+
+	if (g_rdp_version >= RDP_V5 && g_negotiate_rdp_protocol)
+		length += 8;
+
+	s = tcp_init(length);
+
+	out_uint8(s, 3);	/* version */
+	out_uint8(s, 0);	/* reserved */
+	out_uint16_be(s, length);	/* length */
+
+	out_uint8(s, length - 5);	/* hdrlen */
+	out_uint8(s, ISO_PDU_CR);
+	out_uint16(s, 0);	/* dst_ref */
+	out_uint16(s, 0);	/* src_ref */
+	out_uint8(s, 0);	/* class */
+
+	out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
+	out_uint8p(s, username, strlen(username));
+
+	out_uint8(s, 0x0d);	/* cookie termination string: CR+LF */
+	out_uint8(s, 0x0a);
+
+	if (g_rdp_version >= RDP_V5 && g_negotiate_rdp_protocol)
+	{
+		/* optional rdp protocol negotiation request for RDPv5 */
+		out_uint8(s, RDP_NEG_REQ);
+		out_uint8(s, 0);
+		out_uint16(s, 8);
+		out_uint32(s, neg_proto);
+	}
+
+	s_mark_end(s);
+	tcp_send(s);
+}
+
+/* Receive a message on the ISO layer, return code */
+static STREAM
+iso_recv_msg(uint8 * code, uint8 * rdpver)
+{
+	STREAM s;
+	uint16 length;
+	uint8 version;
+
+	s = tcp_recv(NULL, 4);
+	if (s == NULL)
+		return NULL;
+	in_uint8(s, version);
+	if (rdpver != NULL)
+		*rdpver = version;
+	if (version == 3)
+	{
+		in_uint8s(s, 1);	/* pad */
+		in_uint16_be(s, length);
+	}
+	else
+	{
+		in_uint8(s, length);
+		if (length & 0x80)
+		{
+			length &= ~0x80;
+			next_be(s, length);
+		}
+	}
+	if (length < 4)
+	{
+		error("Bad packet header\n");
+		return NULL;
+	}
+	s = tcp_recv(s, length - 4);
+	if (s == NULL)
+		return NULL;
+	if (version != 3)
+		return s;
+	in_uint8s(s, 1);	/* hdrlen */
+	in_uint8(s, *code);
+	if (*code == ISO_PDU_DT)
+	{
+		in_uint8s(s, 1);	/* eot */
+		return s;
+	}
+	in_uint8s(s, 5);	/* dst_ref, src_ref, class */
+	return s;
+}
+
+/* Initialise ISO transport data packet */
+STREAM
+iso_init(int length)
+{
+	STREAM s;
+
+	s = tcp_init(length + 7);
+	s_push_layer(s, iso_hdr, 7);
+
+	return s;
+}
+
+/* Send an ISO data PDU */
+void
+iso_send(STREAM s)
+{
+	uint16 length;
+
+	s_pop_layer(s, iso_hdr);
+	length = s->end - s->p;
+
+	out_uint8(s, 3);	/* version */
+	out_uint8(s, 0);	/* reserved */
+	out_uint16_be(s, length);
+
+	out_uint8(s, 2);	/* hdrlen */
+	out_uint8(s, ISO_PDU_DT);	/* code */
+	out_uint8(s, 0x80);	/* eot */
+
+	tcp_send(s);
+}
+
+/* Receive ISO transport data packet */
+STREAM
+iso_recv(uint8 * rdpver)
+{
+	STREAM s;
+	uint8 code = 0;
+
+	s = iso_recv_msg(&code, rdpver);
+	if (s == NULL)
+		return NULL;
+	if (rdpver != NULL)
+		if (*rdpver != 3)
+			return s;
+	if (code != ISO_PDU_DT)
+	{
+		error("expected DT, got 0x%x\n", code);
+		return NULL;
+	}
+	return s;
+}
+
+/* Establish a connection up to the ISO layer */
+RD_BOOL
+iso_connect(char *server, char *username, char *domain, char *password,
+	    RD_BOOL reconnect, uint32 * selected_protocol)
+{
+	STREAM s;
+	uint8 code;
+	uint32 neg_proto;
+
+	g_negotiate_rdp_protocol = True;
+
+	neg_proto = PROTOCOL_SSL;
+
+#ifdef WITH_CREDSSP
+	if (!g_use_password_as_pin)
+		neg_proto |= PROTOCOL_HYBRID;
+	else if (g_sc_csp_name || g_sc_reader_name || g_sc_card_name || g_sc_container_name)
+		neg_proto |= PROTOCOL_HYBRID;
+	else
+		warning("Disables CredSSP due to missing smartcard information for SSO.\n");
+#endif
+
+      retry:
+	*selected_protocol = PROTOCOL_RDP;
+	code = 0;
+
+	if (!tcp_connect(server))
+		return False;
+
+	iso_send_connection_request(username, neg_proto);
+
+	s = iso_recv_msg(&code, NULL);
+	if (s == NULL)
+		return False;
+
+	if (code != ISO_PDU_CC)
+	{
+		error("expected CC, got 0x%x\n", code);
+		tcp_disconnect();
+		return False;
+	}
+
+	if (g_rdp_version >= RDP_V5 && s_check_rem(s, 8))
+	{
+		/* handle RDP_NEG_REQ response */
+		const char *reason = NULL;
+
+		uint8 type = 0, flags = 0;
+		uint16 length = 0;
+		uint32 data = 0;
+
+		in_uint8(s, type);
+		in_uint8(s, flags);
+		in_uint16(s, length);
+		in_uint32(s, data);
+
+		if (type == RDP_NEG_FAILURE)
+		{
+			RD_BOOL retry_without_neg = False;
+
+			switch (data)
+			{
+				case SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER:
+					reason = "SSL with user authentication required by server";
+					break;
+				case SSL_NOT_ALLOWED_BY_SERVER:
+					reason = "SSL not allowed by server";
+					retry_without_neg = True;
+					break;
+				case SSL_CERT_NOT_ON_SERVER:
+					reason = "no valid authentication certificate on server";
+					retry_without_neg = True;
+					break;
+				case INCONSISTENT_FLAGS:
+					reason = "inconsistent negotiation flags";
+					break;
+				case SSL_REQUIRED_BY_SERVER:
+					reason = "SSL required by server";
+					break;
+				case HYBRID_REQUIRED_BY_SERVER:
+					reason = "CredSSP required by server";
+					break;
+				default:
+					reason = "unknown reason";
+			}
+
+			tcp_disconnect();
+
+			if (retry_without_neg)
+			{
+				fprintf(stderr,
+					"Failed to negotiate protocol, retrying with plain RDP.\n");
+				g_negotiate_rdp_protocol = False;
+				goto retry;
+			}
+
+			fprintf(stderr, "Failed to connect, %s.\n", reason);
+			return False;
+		}
+
+		if (type != RDP_NEG_RSP)
+		{
+			tcp_disconnect();
+			error("Expected RDP_NEG_RSP, got type = 0x%x\n", type);
+			return False;
+		}
+
+		/* handle negotiation response */
+		if (data == PROTOCOL_SSL)
+		{
+			if (!tcp_tls_connect())
+			{
+				/* failed to connect using cssp, let retry with plain TLS */
+				tcp_disconnect();
+				neg_proto = PROTOCOL_RDP;
+				goto retry;
+			}
+			/* do not use encryption when using TLS */
+			g_encryption = False;
+			fprintf(stderr, "Connection established using SSL.\n");
+		}
+#ifdef WITH_CREDSSP
+		else if (data == PROTOCOL_HYBRID)
+		{
+			if (!cssp_connect(server, username, domain, password, s))
+			{
+				/* failed to connect using cssp, let retry with plain TLS */
+				tcp_disconnect();
+				neg_proto = PROTOCOL_SSL;
+				goto retry;
+			}
+
+			/* do not use encryption when using TLS */
+			fprintf(stderr, "Connection established using CredSSP.\n");
+			g_encryption = False;
+		}
+#endif
+		else if (data == PROTOCOL_RDP)
+		{
+			fprintf(stderr, "Connection established using plain RDP.\n");
+		}
+		else if (data != PROTOCOL_RDP)
+		{
+			tcp_disconnect();
+			error("Unexpected protocol in negotiation response, got data = 0x%x.\n",
+			      data);
+			return False;
+		}
+
+		*selected_protocol = data;
+	}
+	return True;
+}
+
+/* Disconnect from the ISO layer */
+void
+iso_disconnect(void)
+{
+	iso_send_msg(ISO_PDU_DR);
+	tcp_disconnect();
+}
+
+/* reset the state to support reconnecting */
+void
+iso_reset_state(void)
+{
+	g_encryption = g_encryption_initial;
+	tcp_reset_state();
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/ar
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/ar	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/ar	(revision 55121)
@@ -0,0 +1,98 @@
+# generated from XKB map ar
+include common
+map 0x401
+exclam 0x02 shift
+at 0x03 shift
+numbersign 0x04 shift
+dollar 0x05 shift
+percent 0x06 shift
+asciicircum 0x07 shift
+ampersand 0x08 shift
+asterisk 0x09 shift
+parenleft 0x0a shift
+parenright 0x0b shift
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+Arabic_dad 0x10 altgr
+Arabic_fatha 0x10 shift altgr
+Arabic_sad 0x11 altgr
+Arabic_fathatan 0x11 shift altgr
+Arabic_theh 0x12 altgr
+Arabic_damma 0x12 shift altgr
+Arabic_qaf 0x13 altgr
+Arabic_dammatan 0x13 shift altgr
+Arabic_feh 0x14 altgr
+UFEF9 0x14 shift altgr
+Arabic_ghain 0x15 altgr
+Arabic_hamzaunderalef 0x15 shift altgr
+Arabic_ain 0x16 altgr
+grave 0x16 shift altgr
+Arabic_ha 0x17 altgr
+division 0x17 shift altgr
+Arabic_khah 0x18 altgr
+multiply 0x18 shift altgr
+Arabic_hah 0x19 altgr
+Arabic_semicolon 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+Arabic_jeem 0x1a altgr
+bracketright 0x1b
+braceright 0x1b shift
+Arabic_dal 0x1b altgr
+Arabic_sheen 0x1e altgr
+backslash 0x1e shift altgr
+Arabic_seen 0x1f altgr
+Arabic_yeh 0x20 altgr
+bracketleft 0x20 shift altgr
+Arabic_beh 0x21 altgr
+bracketright 0x21 shift altgr
+Arabic_lam 0x22 altgr
+UFEF7 0x22 shift altgr
+Arabic_alef 0x23 altgr
+Arabic_hamzaonalef 0x23 shift altgr
+Arabic_teh 0x24 altgr
+Arabic_tatweel 0x24 shift altgr
+Arabic_noon 0x25 altgr
+Arabic_comma 0x25 shift altgr
+Arabic_meem 0x26 altgr
+slash 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+Arabic_kaf 0x27 altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+Arabic_tah 0x28 altgr
+grave 0x29
+asciitilde 0x29 shift
+Arabic_thal 0x29 altgr
+Arabic_shadda 0x29 shift altgr
+backslash 0x2b
+bar 0x2b shift
+less 0x2b altgr
+greater 0x2b shift altgr
+Arabic_hamzaonyeh 0x2c altgr
+asciitilde 0x2c shift altgr
+Arabic_hamza 0x2d altgr
+Arabic_sukun 0x2d shift altgr
+Arabic_hamzaonwaw 0x2e altgr
+Arabic_kasra 0x2e shift altgr
+Arabic_ra 0x2f altgr
+Arabic_kasratan 0x2f shift altgr
+UFEFB 0x30 altgr
+UFEF5 0x30 shift altgr
+Arabic_alefmaksura 0x31 altgr
+Arabic_maddaonalef 0x31 shift altgr
+Arabic_tehmarbuta 0x32 altgr
+apostrophe 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+Arabic_waw 0x33 altgr
+period 0x34
+greater 0x34 shift
+Arabic_zain 0x34 altgr
+slash 0x35
+question 0x35 shift
+Arabic_zah 0x35 altgr
+Arabic_question_mark 0x35 shift altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/common
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/common	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/common	(revision 55121)
@@ -0,0 +1,229 @@
+include modifiers
+
+#
+# Top row
+#
+1 0x2
+2 0x3
+3 0x4
+4 0x5
+5 0x6
+6 0x7
+7 0x8
+8 0x9
+9 0xa
+0 0xb
+BackSpace 0xe
+
+#
+# QWERTY first row
+#
+Tab 0xf localstate
+ISO_Left_Tab 0xf shift
+q 0x10 addupper
+w 0x11 addupper
+e 0x12 addupper
+sequence egrave dead_grave e
+sequence Egrave dead_grave E
+sequence eacute dead_acute e
+sequence Eacute dead_acute E
+sequence ecircumflex dead_circumflex e 
+sequence Ecircumflex dead_circumflex E 
+sequence ediaeresis dead_diaeresis e
+sequence Ediaeresis dead_diaeresis E
+r 0x13 addupper
+t 0x14 addupper
+y 0x15 addupper
+sequence ygrave dead_grave y
+sequence Ygrave dead_grave Y
+sequence yacute dead_acute y
+sequence Yacute dead_acute Y
+sequence ycircumflex dead_circumflex y
+sequence Ycircumflex dead_circumflex Y 
+sequence ydiaeresis dead_diaeresis y
+sequence Ydiaeresis dead_diaeresis Y
+u 0x16 addupper
+sequence ugrave dead_grave u
+sequence Ugrave dead_grave U
+sequence uacute dead_acute u
+sequence Uacute dead_acute U
+sequence ucircumflex dead_circumflex u 
+sequence Ucircumflex dead_circumflex U 
+sequence udiaeresis dead_diaeresis u
+sequence Udiaeresis dead_diaeresis U
+i 0x17 addupper
+sequence igrave dead_grave i
+sequence Igrave dead_grave I
+sequence iacute dead_acute i
+sequence Iacute dead_acute I
+sequence icircumflex dead_circumflex i 
+sequence Icircumflex dead_circumflex I 
+sequence idiaeresis dead_diaeresis i
+sequence Idiaeresis dead_diaeresis I
+o 0x18 addupper
+sequence ograve dead_grave o
+sequence Ograve dead_grave O
+sequence oacute dead_acute o
+sequence Oacute dead_acute O
+sequence ocircumflex dead_circumflex o 
+sequence Ocircumflex dead_circumflex O 
+sequence odiaeresis dead_diaeresis o
+sequence Odiaeresis dead_diaeresis O
+sequence otilde dead_tilde o
+sequence Otilde dead_tilde O
+p 0x19 addupper
+
+#
+# QWERTY second row
+#
+a 0x1e addupper
+sequence agrave dead_grave a
+sequence Agrave dead_grave A
+sequence aacute dead_acute a
+sequence Aacute dead_acute A
+sequence acircumflex dead_circumflex a 
+sequence Acircumflex dead_circumflex A 
+sequence adiaeresis dead_diaeresis a
+sequence Adiaeresis dead_diaeresis A
+sequence aring dead_abovering a
+sequence Aring dead_abovering A
+sequence atilde dead_tilde a
+sequence Atilde dead_tilde A
+s 0x1f addupper
+d 0x20 addupper
+f 0x21 addupper
+g 0x22 addupper
+h 0x23 addupper
+j 0x24 addupper
+k 0x25 addupper
+l 0x26 addupper
+Return 0x1c localstate
+
+#
+# QWERTY third row
+#
+z 0x2c addupper
+x 0x2d addupper
+c 0x2e addupper
+sequence ccedilla dead_cedilla c
+sequence Ccedilla dead_cedilla C
+v 0x2f addupper
+b 0x30 addupper
+n 0x31 addupper
+sequence ntilde dead_tilde n
+sequence Ntilde dead_tilde N
+m 0x32 addupper
+
+space 0x39 localstate
+
+less 0x56
+greater 0x56 shift
+bar 0x56 altgr
+brokenbar 0x56 shift altgr
+
+#
+# Translations for some other dead keys
+#
+sequence asciitilde dead_tilde space
+sequence diaeresis dead_diaeresis space
+sequence asciicircum dead_circumflex space
+sequence apostrophe dead_acute space
+sequence grave dead_grave space
+sequence acute dead_acute space
+
+#
+# Esc and Function keys
+#
+Escape 0x1 localstate
+F1 0x3b localstate
+F2 0x3c localstate
+F3 0x3d localstate
+F4 0x3e localstate
+F5 0x3f localstate
+F6 0x40 localstate
+F7 0x41 localstate
+F8 0x42 localstate
+F9 0x43 localstate
+F10 0x44 localstate
+F11 0x57 localstate
+SunF36 0x57 localstate
+F12 0x58 localstate
+SunF37 0x58 localstate
+
+# Printscreen, Scrollock and Pause
+# Printscreen really requires four scancodes (0xe0, 0x2a, 0xe0, 0x37),
+# but (0xe0, 0x37) seems to work. 
+Print 0xb7 localstate
+Sys_Req 0xb7 localstate
+Execute 0xb7 localstate
+F22 0xb7 localstate
+Scroll_Lock 0x46
+F23 0x46
+
+#
+# Insert - PgDown
+#
+Insert 0xd2 localstate
+Delete 0xd3 localstate
+Home 0xc7 localstate
+End 0xcf localstate
+Page_Up 0xc9 localstate
+Page_Down 0xd1 localstate
+
+#
+# Arrow keys
+#
+Left 0xcb localstate
+Up 0xc8 localstate
+Down 0xd0 localstate
+Right 0xcd localstate
+
+#
+# Numpad
+#
+Num_Lock 0x45
+KP_Divide 0xb5 localstate
+KP_Multiply 0x37 localstate
+KP_Subtract 0x4a localstate
+KP_Add 0x4e localstate
+KP_Enter 0x9c localstate
+
+KP_Decimal 0x53 numlock
+KP_Separator 0x53 numlock
+KP_Delete 0x53
+
+KP_0 0x52 numlock
+KP_Insert 0x52 localstate
+
+KP_1 0x4f numlock
+KP_End 0x4f localstate
+
+KP_2 0x50 numlock
+KP_Down 0x50 localstate
+
+KP_3 0x51 numlock
+KP_Next 0x51 localstate
+
+KP_4 0x4b numlock
+KP_Left 0x4b localstate
+
+KP_5 0x4c numlock
+KP_Begin 0x4c localstate
+
+KP_6 0x4d numlock
+KP_Right 0x4d localstate
+
+KP_7 0x47 numlock
+KP_Home 0x47 localstate
+
+KP_8 0x48 numlock
+KP_Up 0x48 localstate
+
+KP_9 0x49 numlock
+KP_Prior 0x49 localstate
+
+#
+# Inhibited keys
+#
+Caps_Lock 0x0 inhibit
+Multi_key 0x0 inhibit
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/convert-map
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/convert-map	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/convert-map	(revision 55121)
@@ -0,0 +1,62 @@
+#!/usr/bin/env python2
+# -*-Python-*-
+#
+# Copyright 2001 Peter Åstrand <astrand@cendio.se> for Cendio AB
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License. 
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+import sys
+
+def main():
+    f = open(sys.argv[1])
+    while 1:
+        line = f.readline()
+        if not line: break
+
+        if line.startswith("#") or line.startswith("include"):
+            print line,
+            continue
+
+        fields = line.split()
+
+        if line.startswith("map"):
+            print "map 0x%s" % fields[1]
+            continue
+
+        scancode = fields[0]
+        for pos in range(1, len(fields)):
+            keysym = fields[pos]
+
+            if pos == 1:
+                modifiers = ""
+            elif pos == 2:
+                modifiers = "shift"
+            elif pos == 3:
+                modifiers = "altgr"
+            elif pos == 4:
+                modifiers = "shift altgr"
+            else:
+                raise("Invalid line: %s" % line)
+            
+            print "%s 0x%s %s" % (keysym, scancode, modifiers)
+
+
+
+if __name__ == "__main__":
+    if len(sys.argv) < 2:
+        print "Convert old-style keymaps to new style"
+        print "Usage: %s <old-style-keymap>" % sys.argv[0]
+        sys.exit(1)
+    else:
+        main()
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/cs
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/cs	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/cs	(revision 55121)
@@ -0,0 +1,187 @@
+#Czech keymap
+#2007-05-28 by Jaroslav Jiricka <giahra@atlas.cz>
+include common
+
+#Additional sequences
+#2007-05-28 by Jaroslav Jiricka <giahra@atlas.cz>
+
+sequence ecaron dead_caron e
+sequence Ecaron dead_caron E
+sequence eogonek dead_ogonek e
+sequence Eogonek dead_ogonek E
+
+sequence rcaron dead_caron r
+sequence Rcaron dead_caron R
+sequence racute dead_acute r
+sequence Racute dead_acute R
+
+sequence tcaron dead_caron t
+sequence Tcaron dead_caron T
+sequence tcedilla dead_cedilla t
+sequence Tcedilla dead_cedilla T
+
+sequence zcaron dead_caron z
+sequence Zcaron dead_caron Z
+sequence zacute dead_acute z
+sequence Zacute dead_acute Z
+sequence zabovedot dead_abovedot z
+sequence Zabovedot dead_abovedot Z
+
+sequence uring dead_abovering u
+sequence Uring dead_abovering U
+sequence udoubleacute dead_doubleacute u
+sequence Udoubleacute dead_doubleacute U
+
+sequence odoubleacute dead_doubleacute o
+sequence Odoubleacute dead_doubleacute O
+
+sequence aogonek dead_ogonek a
+sequence Aogonek dead_ogonek A
+sequence abreve dead_breve a
+sequence Abreve dead_breve A
+
+sequence scaron dead_caron s
+sequence Scaron dead_caron S
+sequence sacute dead_acute s
+sequence Sacute dead_acute S
+sequence scedilla dead_cedilla s
+sequence Scedilla dead_cedilla S
+
+sequence dcaron dead_caron d
+sequence Dcaron dead_caron D
+
+sequence gbreve dead_breve g
+sequence Gbreve dead_breve G
+
+sequence lcaron dead_caron l
+sequence Lcaron dead_caron L
+sequence lacute dead_acute l
+sequence Lacute dead_acute L
+
+sequence ccaron dead_caron c
+sequence Ccaron dead_caron C
+
+sequence ncaron dead_caron n
+sequence Ncaron dead_caron N
+sequence nacute dead_acute n
+sequence Nacute dead_acute N
+#Additional sequences end
+
+map 0x405
+
+semicolon 0x29
+dead_abovering 0x29 shift
+
+plus 0x02
+1 0x02 shift
+dead_tilde 0x02 altgr
+asciitilde 0x02 altgr
+
+ecaron 0x03
+2 0x03 shift
+dead_caron 0x03 altgr
+
+scaron 0x04
+3 0x04 shift
+dead_circumflex 0x04 altgr
+
+ccaron 0x05
+4 0x05 shift
+dead_breve 0x05 altgr
+
+rcaron 0x06
+5 0x06 shift
+dead_abovering 0x06 altgr
+
+zcaron 0x07
+6 0x07 shift
+dead_ogonek 0x07 altgr
+
+yacute 0x08
+7 0x08 shift
+dead_grave 0x08 altgr
+
+aacute 0x09
+8 0x09 shift
+dead_abovedot 0x08 altgr
+
+iacute 0x0a
+9 0x0a shift
+dead_acute 0x08 altgr
+
+eacute 0x0b
+0 0x0b shift
+dead_doubleacute 0x0b altgr
+
+equal 0x0c
+percent 0x0c shift
+dead_macron 0x0c altgr
+
+dead_acute 0x0d
+dead_caron 0x0d shift
+dead_cedilla 0x0d altgr
+
+backslash 0x10 altgr
+
+bar 0x11 altgr
+
+EuroSign 0x12 altgr
+
+z 0x15 addupper
+
+uacute 0x1a
+slash 0x1a shift
+division 0x1a altgr
+
+parenright 0x1b
+parenleft 0x1b shift
+multiply 0x1b altgr
+
+dead_diaeresis 0x2b
+apostrophe 0x2b shift
+currency 0x2b altgr
+
+dstroke 0x1f altgr
+
+Dstroke 0x20 altgr
+
+bracketleft 0x21 altgr
+
+bracketright 0x22 altgr
+
+lstroke 0x25 altgr
+
+Lstroke 0x26 altgr
+
+uring 0x27
+quotedbl 0x27 shift
+dollar 0x27 altgr
+
+section 0x28
+exclam 0x28 shift
+ssharp 0x28 altgr
+
+y 0x2c addupper
+
+numbersign 0x2d altgr
+
+ampersand 0x2e altgr
+
+at 0x2f altgr
+
+braceleft 0x30 altgr
+
+braceright 0x31 altgr
+
+comma 0x33
+question 0x33 shift
+less 0x33 altgr
+
+period 0x34
+colon 0x34 shift
+greater 0x34 altgr
+
+minus 0x35
+underscore 0x35 shift
+asterisk 0x35 altgr
+
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/da
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/da	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/da	(revision 55121)
@@ -0,0 +1,120 @@
+# generated from XKB map dk
+include common
+map 0x406
+exclam 0x02 shift
+exclamdown 0x02 altgr
+onesuperior 0x02 shift altgr
+quotedbl 0x03 shift
+at 0x03 altgr
+twosuperior 0x03 shift altgr
+numbersign 0x04 shift
+sterling 0x04 altgr
+threesuperior 0x04 shift altgr
+currency 0x05 shift
+dollar 0x05 altgr
+onequarter 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+cent 0x06 shift altgr
+ampersand 0x07 shift
+yen 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+division 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+guillemotleft 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+guillemotright 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+plus 0x0c
+question 0x0c shift
+plusminus 0x0c altgr
+questiondown 0x0c shift altgr
+dead_acute 0x0d
+dead_grave 0x0d shift
+bar 0x0d altgr
+brokenbar 0x0d shift altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+registered 0x13 altgr
+thorn 0x14 altgr
+THORN 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oe 0x18 altgr
+OE 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+aring 0x1a
+Aring 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+dead_diaeresis 0x1b
+dead_circumflex 0x1b shift
+dead_tilde 0x1b altgr
+dead_caron 0x1b shift altgr
+ordfeminine 0x1e altgr
+masculine 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+ae 0x27
+AE 0x27 shift
+oslash 0x28
+Ooblique 0x28 shift
+dead_caron 0x28 shift altgr
+onehalf 0x29
+section 0x29 shift
+threequarters 0x29 altgr
+paragraph 0x29 shift altgr
+apostrophe 0x2b
+asterisk 0x2b shift
+dead_doubleacute 0x2b altgr
+multiply 0x2b shift altgr
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+copyright 0x2e altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+dead_cedilla 0x33 altgr
+dead_ogonek 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+dead_abovedot 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+hyphen 0x35 altgr
+macron 0x35 shift altgr
+nobreakspace 0x39 altgr
+less 0x56
+greater 0x56 shift
+backslash 0x56 altgr
+notsign 0x56 shift altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/de
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/de	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/de	(revision 55121)
@@ -0,0 +1,114 @@
+# generated from XKB map de
+include common
+map 0x407
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+quotedbl 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+section 0x04 shift
+threesuperior 0x04 altgr
+sterling 0x04 shift altgr
+dollar 0x05 shift
+onequarter 0x05 altgr
+currency 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+ssharp 0x0c
+question 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+acute 0x0d
+dead_acute 0x0d
+grave 0x0d shift
+dead_grave 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+z 0x15 addupper
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+udiaeresis 0x1a
+Udiaeresis 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+plus 0x1b
+asterisk 0x1b shift
+asciitilde 0x1b altgr
+dead_tilde 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+odiaeresis 0x27
+Odiaeresis 0x27 shift
+dead_doubleacute 0x27 altgr
+adiaeresis 0x28
+Adiaeresis 0x28 shift
+dead_caron 0x28 shift altgr
+asciicircum 0x29
+dead_circumflex 0x29
+degree 0x29 shift
+notsign 0x29 altgr
+numbersign 0x2b
+apostrophe 0x2b shift
+dead_breve 0x2b shift altgr
+y 0x2c addupper
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/de-ch
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/de-ch	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/de-ch	(revision 55121)
@@ -0,0 +1,169 @@
+# rdesktop Swiss-German (de-ch) keymap file 
+# 2003-06-03 by noldi@tristar.ch 
+#
+include common
+map 0x00000807
+#
+# Scan Code 1
+section 0x29
+degree 0x29 shift
+notsign 0x29 altgr inhibit
+#
+# Scan Code 2
+plus 0x2 shift
+brokenbar 0x02 altgr
+#
+# Scan Code 3
+quotedbl 0x03 shift
+at 0x03 altgr
+#
+# Scan Code 4
+asterisk 0x04 shift
+numbersign 0x04 altgr
+#
+# Scan Code 5
+ccedilla 0x05 shift
+onequarter 0x05 altgr inhibit
+#
+# Scan Code 6
+percent 0x06 shift
+onehalf 0x06 altgr inhibit
+#
+# Scan Code 7
+ampersand 0x07 shift
+notsign 0x07 altgr
+#
+# Scan Code 8
+slash 0x08 shift
+bar 0x08 altgr
+#
+# Scan Code 9
+parenleft 0x09 shift
+cent 0x09 altgr
+# 
+# Scan Code 10
+parenright 0x0a shift
+#
+# Scan Code 11
+equal 0x0b shift
+braceright 0x0b altgr inhibit
+#
+# Scan Code 12
+apostrophe 0x0c 
+question 0x0c shift
+dead_acute 0x0c altgr
+#
+# Scan Code 13
+dead_circumflex 0x0d
+dead_grave 0x0d shift
+dead_tilde 0x0d altgr
+#
+# Scan Code 19
+EuroSign 0x12 altgr
+#
+# Scan Code 22
+z 0x15 addupper
+#
+# Scan Code 27
+udiaeresis 0x1a
+egrave 0x1a shift
+bracketleft 0x1a altgr
+# 
+# Scan Code 28
+dead_diaeresis 0x1b
+exclam 0x1b shift 
+bracketright 0x1b altgr
+#
+# Scan Code 40
+odiaeresis 0x27
+eacute 0x27 shift
+#
+# Scan Code 41
+adiaeresis 0x28
+agrave 0x28 shift
+braceleft 0x28 altgr
+#
+# Scan Code 42 (only on international keyboards)
+dollar 0x2b
+sterling 0x2b shift
+braceright 0x2b altgr
+#
+# Scan Code 45 (only on international keyboards)
+backslash 0x56 altgr
+#
+# Scan Code 46
+y 0x2c addupper
+# 
+# Scan Code 53
+comma 0x33
+semicolon 0x33 shift
+# 
+# Scan Code 54
+period 0x34
+colon 0x34 shift
+#
+# Scan Code 55
+minus 0x35 
+underscore 0x35 shift
+#
+# Suppress Windows unsupported AltGr keys
+#
+# Scan Code 17
+paragraph 0x10 altgr inhibit
+#
+# Scan Code 21
+tslash 0x14 altgr inhibit
+#
+# Scan Code 22
+leftarrow 0x15 altgr inhibit
+#
+# Scan Code 23
+downarrow 0x16 altgr inhibit
+#
+# Scan Code 24
+rightarrow 0x17 altgr inhibit
+#
+# Scan Code 25
+oslash 0x18 altgr inhibit
+#
+# Scan Code 26
+thorn 0x19 altgr inhibit
+#
+# Scan Code 31
+ae 0x1e altgr inhibit
+#
+# Scan Code 32
+ssharp 0x1f altgr inhibit
+#
+# Scan Code 33
+eth 0x20 altgr inhibit
+#
+# Scan Code 34
+dstroke 0x21 altgr inhibit
+#
+# Scan Code 35
+eng 0x22 altgr inhibit
+#
+# Scan Code 36
+hstroke 0x23 altgr inhibit
+#
+# Scan Code 38
+kra 0x25 altgr inhibit
+#
+# Scan Code 39
+lstroke 0x26 altgr inhibit
+#
+# Scan Code 46
+guillemotleft 0x2c altgr inhibit
+#
+# Scan Code 47
+guillemotright 0x2d altgr inhibit
+#
+# Scan Code 49
+leftdoublequotemark 0x2f altgr inhibit
+#
+# Scan Code 50
+rightdoublequotemark 0x30 altgr inhibit
+#
+# Scan Code 52
+mu 0x32 altgr inhibit
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/en-dv
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/en-dv	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/en-dv	(revision 55121)
@@ -0,0 +1,216 @@
+# American Dvorak
+map 0x10409
+
+# Note: we are not including the common section
+include modifiers
+
+#
+# Top row
+#
+1 0x2
+2 0x3
+3 0x4
+4 0x5
+5 0x6
+6 0x7
+7 0x8
+8 0x9
+9 0xa
+0 0xb
+BackSpace 0xe
+
+#
+# QWERTY first row
+
+# QWERTY:
+# q w e r t y u i o p
+
+# Dvorak:
+# ' , . p y f g c r l
+
+Tab 0xf localstate
+ISO_Left_Tab 0xf shift
+q 0x2d addupper
+w 0x33 addupper
+e 0x20 addupper
+r 0x18 addupper
+t 0x25 addupper
+y 0x14 addupper
+u 0x21 addupper
+i 0x22 addupper
+o 0x1f addupper
+p 0x13 addupper
+
+#
+# QWERTY second row
+
+# QUERTY:
+# a s d f g h j k l
+
+# Dvorak:
+# a o e u i d h t n
+ 
+a 0x1e addupper
+s 0x27 addupper
+d 0x23 addupper
+f 0x15 addupper
+g 0x16 addupper
+h 0x24 addupper
+j 0x2e addupper
+k 0x2f addupper
+l 0x19 addupper
+Return 0x1c localstate
+
+#
+# QWERTY third row
+
+# QUERTY:
+# z x c v b n m
+
+# Dvorak:
+# ; q j k x b m
+
+z 0x35 addupper
+x 0x30 addupper
+c 0x17 addupper
+v 0x34 addupper
+b 0x31 addupper
+n 0x26 addupper
+m 0x32 addupper
+
+space 0x39 localstate
+
+less 0x56
+greater 0x56 shift
+bar 0x56 altgr
+brokenbar 0x56 shift altgr
+
+#
+# Esc and Function keys
+#
+Escape 0x1 localstate
+F1 0x3b localstate
+F2 0x3c localstate
+F3 0x3d localstate
+F4 0x3e localstate
+F5 0x3f localstate
+F6 0x40 localstate
+F7 0x41 localstate
+F8 0x42 localstate
+F9 0x43 localstate
+F10 0x44 localstate
+F11 0x57 localstate
+SunF36 0x57 localstate
+F12 0x58 localstate
+SunF37 0x58 localstate
+
+# Printscreen, Scrollock and Pause
+# Printscreen really requires four scancodes (0xe0, 0x2a, 0xe0, 0x37),
+# but (0xe0, 0x37) seems to work. 
+Print 0xb7 localstate
+Sys_Req 0xb7 localstate
+Execute 0xb7 localstate
+F22 0xb7 localstate
+Scroll_Lock 0x46
+F23 0x46
+
+#
+# Insert - PgDown
+#
+Insert 0xd2 localstate
+Delete 0xd3 localstate
+Home 0xc7 localstate
+End 0xcf localstate
+Page_Up 0xc9 localstate
+Page_Down 0xd1 localstate
+
+#
+# Arrow keys
+#
+Left 0xcb localstate
+Up 0xc8 localstate
+Down 0xd0 localstate
+Right 0xcd localstate
+
+#
+# Numpad
+#
+Num_Lock 0x45
+KP_Divide 0xb5
+KP_Multiply 0x37
+KP_Subtract 0x4a
+KP_Add 0x4e
+KP_Enter 0x9c
+
+KP_Decimal 0x53 numlock
+KP_Separator 0x53 numlock
+KP_Delete 0x53
+
+KP_0 0x52 numlock
+KP_Insert 0x52
+
+KP_1 0x4f numlock
+KP_End 0x4f
+
+KP_2 0x50 numlock
+KP_Down 0x50
+
+KP_3 0x51 numlock
+KP_Next 0x51
+
+KP_4 0x4b numlock
+KP_Left 0x4b
+
+KP_5 0x4c numlock
+KP_Begin 0x4c
+
+KP_6 0x4d numlock
+KP_Right 0x4d
+
+KP_7 0x47 numlock
+KP_Home 0x47
+
+KP_8 0x48 numlock
+KP_Up 0x48
+
+KP_9 0x49 numlock
+KP_Prior 0x49
+
+#
+# Inhibited keys
+#
+Caps_Lock 0x0 inhibit
+Multi_key 0x0 inhibit
+
+exclam 0x02 shift
+at 0x03 shift
+numbersign 0x04 shift
+dollar 0x05 shift
+percent 0x06 shift
+asciicircum 0x07 shift
+ampersand 0x08 shift
+asterisk 0x09 shift
+parenleft 0x0a shift
+parenright 0x0b shift
+minus 0x28
+underscore 0x28 shift
+equal 0x1b
+plus 0x1b shift
+bracketleft 0x0c
+braceleft 0x0c shift
+bracketright 0x0d
+braceright 0x0d shift
+semicolon 0x2c
+colon 0x2c shift
+apostrophe 0x10
+quotedbl 0x10 shift
+grave 0x29
+asciitilde 0x29 shift
+backslash 0x2b
+bar 0x2b shift
+comma 0x11
+less 0x11 shift
+period 0x12
+greater 0x12 shift
+slash 0x1a
+question 0x1a shift
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/en-gb
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/en-gb	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/en-gb	(revision 55121)
@@ -0,0 +1,119 @@
+# generated from XKB map gb
+include common
+map 0x809
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+quotedbl 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+sterling 0x04 shift
+threesuperior 0x04 altgr
+dollar 0x05 shift
+EuroSign 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+asciicircum 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+ampersand 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+asterisk 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenleft 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+parenright 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+minus 0x0c
+underscore 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+equal 0x0d
+plus 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+dead_tilde 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+apostrophe 0x28
+at 0x28 shift
+dead_circumflex 0x28 altgr
+dead_caron 0x28 shift altgr
+grave 0x29
+notsign 0x29 shift
+bar 0x29 altgr
+numbersign 0x2b
+asciitilde 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+guillemotleft 0x2c altgr
+less 0x2c shift altgr
+guillemotright 0x2d altgr
+greater 0x2d shift altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
+backslash 0x56
+bar 0x56 shift
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/en-us
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/en-us	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/en-us	(revision 55121)
@@ -0,0 +1,35 @@
+# generated from XKB map us
+include common
+map 0x409
+exclam 0x02 shift
+at 0x03 shift
+numbersign 0x04 shift
+dollar 0x05 shift
+percent 0x06 shift
+asciicircum 0x07 shift
+ampersand 0x08 shift
+asterisk 0x09 shift
+parenleft 0x0a shift
+parenright 0x0b shift
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+bracketleft 0x1a
+braceleft 0x1a shift
+bracketright 0x1b
+braceright 0x1b shift
+semicolon 0x27
+colon 0x27 shift
+apostrophe 0x28
+quotedbl 0x28 shift
+grave 0x29
+asciitilde 0x29 shift
+backslash 0x2b
+bar 0x2b shift
+comma 0x33
+less 0x33 shift
+period 0x34
+greater 0x34 shift
+slash 0x35
+question 0x35 shift
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/es
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/es	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/es	(revision 55121)
@@ -0,0 +1,105 @@
+# generated from XKB map es
+include common
+map 0x40a
+exclam 0x02 shift
+bar 0x02 altgr
+quotedbl 0x03 shift
+at 0x03 altgr
+oneeighth 0x03 shift altgr
+periodcentered 0x04 shift
+numbersign 0x04 altgr
+sterling 0x04 shift altgr
+dollar 0x05 shift
+asciitilde 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+notsign 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+trademark 0x09 shift altgr
+parenright 0x0a shift
+plusminus 0x0a shift altgr
+equal 0x0b shift
+degree 0x0b shift altgr
+apostrophe 0x0c
+question 0x0c shift
+exclamdown 0x0d
+questiondown 0x0d shift
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+dead_grave 0x1a
+dead_circumflex 0x1a shift
+bracketleft 0x1a altgr
+dead_abovering 0x1a shift altgr
+plus 0x1b
+asterisk 0x1b shift
+bracketright 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+ntilde 0x27
+Ntilde 0x27 shift
+dead_doubleacute 0x27 shift altgr
+dead_acute 0x28
+dead_diaeresis 0x28 shift
+braceleft 0x28 altgr
+masculine 0x29
+ordfeminine 0x29 shift
+backslash 0x29 altgr
+ccedilla 0x2b
+Ccedilla 0x2b shift
+braceright 0x2b altgr
+dead_breve 0x2b shift altgr
+guillemotleft 0x2c altgr
+less 0x56
+greater 0x56 shift
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+division 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/et
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/et	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/et	(revision 55121)
@@ -0,0 +1,86 @@
+map 0x00000425
+include common
+
+#
+# Top row
+#
+dead_caron 0x29
+dead_tilde 0x29 shift
+
+# 1
+exclam 0x2 shift
+
+# 2
+quotedbl 0x3 shift
+at 0x3 altgr
+
+# 3
+numbersign 0x4 shift
+sterling 0x4 altgr
+# 4
+currency 0x5 shift
+dollar 0x5 altgr
+# 5
+percent 0x6 shift
+# 6
+ampersand 0x7 shift
+# 7
+slash 0x8 shift
+braceleft 0x8 altgr
+# 8
+parenleft 0x9 shift
+bracketleft 0x9 altgr
+# 9
+parenright 0xa shift
+bracketright 0xa altgr
+# 0
+equal 0xb shift
+braceright 0xb altgr
+
+plus 0xc
+question 0xc shift
+backslash 0xc altgr
+
+acute 0xd
+dead_acute 0xd
+grave 0xd shift
+dead_grave 0xd shift
+
+#
+# QWERTY first row
+#
+EuroSign 0x12 altgr
+udiaeresis 0x1a 
+Udiaeresis 0x1a shift
+otilde 0x1b 
+Otilde 0x1b shift
+section 0x1b altgr
+
+#
+# QWERTY second row
+#
+scaron 0x1f altgr
+Scaron 0x1f altgr shift
+odiaeresis 0x27 
+Odiaeresis 0x27 shift
+adiaeresis 0x28 
+Adiaeresis 0x28 shift
+asciicircum 0x28 altgr
+apostrophe 0x2b
+asterisk 0x2b shift
+onehalf 0x2b altgr
+#
+# QWERTY third row
+#
+less 0x56 
+greater 0x56 shift
+bar 0x56 altgr
+zcaron 0x2c altgr
+Zcaron 0x2c altgr shift
+comma 0x33
+semicolon 0x33 shift
+period 0x34
+colon 0x34 shift
+minus 0x35
+underscore 0x35 shift
+
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/fi
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/fi	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/fi	(revision 55121)
@@ -0,0 +1,122 @@
+# Finnish keyboard layout
+# Originally generated from XKB map se_FI (wrong!), modified afterwards.
+
+include common
+map 0x40b
+
+exclam 0x02 shift
+exclamdown 0x02 altgr
+onesuperior 0x02 shift altgr
+quotedbl 0x03 shift
+at 0x03 altgr
+twosuperior 0x03 shift altgr
+numbersign 0x04 shift
+sterling 0x04 altgr
+threesuperior 0x04 shift altgr
+currency 0x05 shift
+dollar 0x05 altgr
+onequarter 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+cent 0x06 shift altgr
+ampersand 0x07 shift
+yen 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+division 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+guillemotleft 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+guillemotright 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+plus 0x0c
+question 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+dead_acute 0x0d
+dead_grave 0x0d shift
+plusminus 0x0d altgr
+notsign 0x0d shift altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+registered 0x13 altgr
+thorn 0x14 altgr
+THORN 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oe 0x18 altgr
+OE 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+aring 0x1a
+Aring 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+dead_diaeresis 0x1b
+dead_circumflex 0x1b shift
+dead_tilde 0x1b altgr
+dead_caron 0x1b shift altgr
+ordfeminine 0x1e altgr
+masculine 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+odiaeresis 0x27
+Odiaeresis 0x27 shift
+oslash 0x27 altgr
+Ooblique 0x27 shift altgr
+adiaeresis 0x28
+Adiaeresis 0x28 shift
+ae 0x28 altgr
+AE 0x28 shift altgr
+section 0x29
+onehalf 0x29 shift
+paragraph 0x29 altgr
+threequarters 0x29 shift altgr
+apostrophe 0x2b
+asterisk 0x2b shift
+acute 0x2b altgr
+multiply 0x2b shift altgr
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+copyright 0x2e altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+dead_cedilla 0x33 altgr
+dead_ogonek 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+dead_abovedot 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+hyphen 0x35 altgr
+macron 0x35 shift altgr
+nobreakspace 0x39 altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/fo
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/fo	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/fo	(revision 55121)
@@ -0,0 +1,77 @@
+map 0x438
+include common
+
+#
+# Top row
+#
+onehalf 0x29
+section 0x29 shift
+
+# 1
+exclam 0x2 shift
+
+# 2
+quotedbl 0x3 shift
+at 0x3 altgr
+
+# 3
+numbersign 0x4 shift
+sterling 0x4 altgr
+# 4
+currency 0x5 shift
+dollar 0x5 altgr
+# 5
+percent 0x6 shift
+# 6
+ampersand 0x7 shift
+# 7
+slash 0x8 shift
+braceleft 0x8 altgr
+# 8
+parenleft 0x9 shift
+bracketleft 0x9 altgr
+# 9
+parenright 0xa shift
+bracketright 0xa altgr
+# 0
+equal 0xb shift
+braceright 0xb altgr
+
+plus 0xc
+question 0xc shift
+plusminus 0xc altgr
+
+bar 0xd altgr
+dead_acute 0xd
+
+#
+# QWERTY first row
+#
+EuroSign 0x12 altgr
+aring 0x1a
+Aring 0x1a shift
+eth 0x1b addupper
+asciitilde 0x1b altgr
+
+#
+# QWERTY second row
+#
+ae 0x27 addupper
+oslash 0x28
+Ooblique 0x28 shift
+apostrophe 0x2b
+asterisk 0x2b shift
+
+#
+# QWERTY third row
+#
+less 0x56
+greater 0x56 shift
+backslash 0x56 altgr
+comma 0x33
+semicolon 0x33 shift
+period 0x34
+colon 0x34 shift
+minus 0x35
+underscore 0x35 shift
+
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr	(revision 55121)
@@ -0,0 +1,181 @@
+include common
+map 0x40c
+#
+# Top row
+#
+twosuperior 0x29
+notsign 0x29 altgr
+
+ampersand 0x02
+1 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+
+eacute 0x03
+2 0x03 shift
+asciitilde 0x03 altgr
+oneeighth 0x03 shift altgr
+
+quotedbl 0x04
+3 0x04 shift
+numbersign 0x04 altgr
+
+apostrophe 0x05
+4 0x05 shift
+braceleft 0x05 altgr
+
+parenleft 0x06
+5 0x06 shift
+bracketleft 0x06 altgr
+threeeighths 0x06 shift altgr
+
+minus 0x07
+6 0x07 shift
+bar 0x07 altgr
+fiveeighths 0x07 shift altgr
+
+egrave 0x08
+7 0x08 shift
+grave 0x08 altgr
+seveneighths 0x08 shift altgr
+
+underscore 0x09
+8 0x09 shift
+backslash 0x09 altgr
+trademark 0x09 shift altgr
+
+ccedilla 0x0a
+9 0x0a shift
+asciicircum 0x0a altgr
+plusminus 0x0a shift altgr
+
+agrave 0x0b
+0 0x0b shift
+at 0x0b altgr
+
+parenright 0x0c
+degree 0x0c shift
+bracketright 0x0c altgr
+questiondown 0x0c shift altgr
+
+equal 0x0d
+plus 0x0d shift
+braceright 0x0d altgr
+dead_ogonek 0x0d shift altgr
+
+#
+# AZERTY first row
+#
+
+a 0x10 addupper
+ae 0x10 altgr
+AE 0x10 shift altgr
+
+z 0x11 addupper
+guillemotleft 0x11 altgr
+
+EuroSign 0x12 altgr
+
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+
+dead_circumflex 0x1a 
+dead_diaeresis 0x1a shift
+dead_abovering 0x1a shift altgr
+
+dollar 0x1b
+sterling 0x1b shift
+currency 0x1b altgr
+dead_macron 0x1b shift altgr
+
+#
+# AZERTY second row
+#
+q 0x1e addupper
+Greek_OMEGA 0x1e shift altgr
+
+ssharp 0x1f altgr
+
+eth 0x20 altgr
+ETH 0x20 shift altgr
+
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+
+eng 0x22 altgr
+ENG 0x22 shift altgr
+
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+
+kra 0x25 altgr
+
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+
+m 0x27 addupper
+masculine 0x27 shift altgr
+
+ugrave 0x28
+percent 0x28 shift
+dead_caron 0x28 shift altgr
+
+asterisk 0x2b
+mu 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+
+#
+# AZERTY third row
+#
+less 0x56
+greater 0x56 shift
+
+w 0x2c addupper
+
+guillemotright 0x2d altgr
+
+cent 0x2e altgr
+copyright 0x2e shift altgr
+
+leftdoublequotemark 0x2f altgr
+
+rightdoublequotemark 0x30 altgr
+
+comma 0x32
+question 0x32 shift
+dead_acute 0x32 altgr
+dead_doubleacute 0x32 shift altgr
+
+semicolon 0x33
+period 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+
+colon 0x34
+slash 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+
+exclam 0x35
+section 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr-be
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr-be	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr-be	(revision 55121)
@@ -0,0 +1,135 @@
+# generated from XKB map be
+include common
+map 0x80c
+ampersand 0x02
+1 0x02 shift
+bar 0x02 altgr
+exclamdown 0x02 shift altgr
+eacute 0x03
+2 0x03 shift
+at 0x03 altgr
+oneeighth 0x03 shift altgr
+quotedbl 0x04
+3 0x04 shift
+numbersign 0x04 altgr
+sterling 0x04 shift altgr
+apostrophe 0x05
+4 0x05 shift
+onequarter 0x05 altgr
+dollar 0x05 shift altgr
+parenleft 0x06
+5 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+section 0x07
+6 0x07 shift
+asciicircum 0x07 altgr
+fiveeighths 0x07 shift altgr
+egrave 0x08
+7 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+exclam 0x09
+8 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+ccedilla 0x0a
+9 0x0a shift
+braceleft 0x0a altgr
+plusminus 0x0a shift altgr
+agrave 0x0b
+0 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+parenright 0x0c
+degree 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+minus 0x0d
+underscore 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+a 0x10 addupper
+Greek_OMEGA 0x10 shift altgr
+z 0x11 addupper
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+dead_circumflex 0x1a
+dead_diaeresis 0x1a shift
+bracketleft 0x1a altgr
+dead_abovering 0x1a shift altgr
+dollar 0x1b
+asterisk 0x1b shift
+bracketright 0x1b altgr
+dead_macron 0x1b shift altgr
+q 0x1e addupper
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+m 0x27 addupper
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+ugrave 0x28
+percent 0x28 shift
+dead_acute 0x28 altgr
+dead_caron 0x28 shift altgr
+twosuperior 0x29
+threesuperior 0x29 shift
+notsign 0x29 altgr
+mu 0x2b
+sterling 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+w 0x2c addupper
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+comma 0x32
+question 0x32 shift
+dead_cedilla 0x32 altgr
+masculine 0x32 shift altgr
+semicolon 0x33
+period 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+colon 0x34
+slash 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+equal 0x35
+plus 0x35 shift
+dead_tilde 0x35 altgr
+dead_abovedot 0x35 shift altgr
+backslash 0x56 altgr
+
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr-ca
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr-ca	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr-ca	(revision 55121)
@@ -0,0 +1,53 @@
+# Canadian French
+# By Simon Germain
+include common
+map 0xc0c
+
+backslash 0x29 altgr
+plusminus 0x2 altgr
+at 0x3 altgr
+sterling 0x4 altgr
+cent 0x5 altgr
+currency 0x6 altgr
+notsign 0x7 altgr
+bar 0x29 shift
+twosuperior 0x9 altgr
+threesuperior 0xa altgr
+onequarter 0xb altgr
+onehalf 0xc altgr
+threequarters 0xd altgr
+section 0x18 altgr
+paragraph 0x19 altgr
+bracketleft 0x1a altgr
+bracketright 0x1b altgr
+asciitilde 0x27 altgr
+braceleft 0x28 altgr
+braceright 0x2b altgr
+less 0x2b
+greater 0x2b shift
+guillemotleft 0x56
+guillemotright 0x56 shift
+degree 0x56 altgr
+mu 0x32 altgr
+eacute 0x35
+dead_acute 0x35 altgr
+dead_grave 0x28
+dead_circumflex 0x1a
+dead_circumflex 0x1a shift
+dead_cedilla 0x1b
+dead_diaeresis 0x1b shift
+exclam 0x2 shift
+quotedbl 0x3 shift
+comma 0x33
+apostrophe 0x33 shift
+period 0x34 shift
+slash 0x4 shift
+dollar 0x5 shift
+percent 0x6 shift
+question 0x7 shift
+ampersand 0x8 shift
+asterisk 0x9 shift
+parenleft 0xa shift
+parenright 0xb shift
+underscore 0xc shift
+plus 0xd shift
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr-ch
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr-ch	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/fr-ch	(revision 55121)
@@ -0,0 +1,169 @@
+# rdesktop suisse-french keymap file 
+#
+#map 0x00000807
+map 0x0000100C
+include common
+#
+# Scan Code 1
+section 0x29
+degree 0x29 shift
+notsign 0x29 altgr inhibit
+#
+# Scan Code 2
+plus 0x2 shift
+brokenbar 0x02 altgr
+#
+# Scan Code 3
+quotedbl 0x03 shift
+at 0x03 altgr
+#
+# Scan Code 4
+asterisk 0x04 shift
+numbersign 0x04 altgr
+#
+# Scan Code 5
+ccedilla 0x05 shift
+onequarter 0x05 altgr inhibit
+#
+# Scan Code 6
+percent 0x06 shift
+onehalf 0x06 altgr inhibit
+#
+# Scan Code 7
+ampersand 0x07 shift
+notsign 0x07 altgr
+#
+# Scan Code 8
+slash 0x08 shift
+bar 0x08 altgr
+#
+# Scan Code 9
+parenleft 0x09 shift
+cent 0x09 altgr
+# 
+# Scan Code 10
+parenright 0x0a shift
+#
+# Scan Code 11
+equal 0x0b shift
+braceright 0x0b altgr inhibit
+#
+# Scan Code 12
+apostrophe 0x0c 
+question 0x0c shift
+dead_acute 0x0c altgr
+#
+# Scan Code 13
+dead_circumflex 0x0d
+dead_grave 0x0d shift
+dead_tilde 0x0d altgr
+#
+# Scan Code 19
+EuroSign 0x12 altgr
+#
+# Scan Code 22
+z 0x15 addupper
+#
+# Scan Code 27
+udiaeresis 0x1a shift
+egrave 0x1a 
+bracketleft 0x1a altgr
+# 
+# Scan Code 28
+dead_diaeresis 0x1b
+exclam 0x1b shift 
+bracketright 0x1b altgr
+#
+# Scan Code 40
+odiaeresis 0x27 shift
+eacute 0x27 
+#
+# Scan Code 41
+adiaeresis 0x28 shift
+agrave 0x28 
+braceleft 0x28 altgr
+#
+# Scan Code 42 (only on international keyboards)
+dollar 0x2b
+sterling 0x2b shift
+braceright 0x2b altgr
+#
+# Scan Code 45 (only on international keyboards)
+backslash 0x56 altgr
+#
+# Scan Code 46
+y 0x2c addupper
+# 
+# Scan Code 53
+comma 0x33
+semicolon 0x33 shift
+# 
+# Scan Code 54
+period 0x34
+colon 0x34 shift
+#
+# Scan Code 55
+minus 0x35 
+underscore 0x35 shift
+#
+# Suppress Windows unsupported AltGr keys
+#
+# Scan Code 17
+paragraph 0x10 altgr inhibit
+#
+# Scan Code 21
+tslash 0x14 altgr inhibit
+#
+# Scan Code 22
+leftarrow 0x15 altgr inhibit
+#
+# Scan Code 23
+downarrow 0x16 altgr inhibit
+#
+# Scan Code 24
+rightarrow 0x17 altgr inhibit
+#
+# Scan Code 25
+oslash 0x18 altgr inhibit
+#
+# Scan Code 26
+thorn 0x19 altgr inhibit
+#
+# Scan Code 31
+ae 0x1e altgr inhibit
+#
+# Scan Code 32
+ssharp 0x1f altgr inhibit
+#
+# Scan Code 33
+eth 0x20 altgr inhibit
+#
+# Scan Code 34
+dstroke 0x21 altgr inhibit
+#
+# Scan Code 35
+eng 0x22 altgr inhibit
+#
+# Scan Code 36
+hstroke 0x23 altgr inhibit
+#
+# Scan Code 38
+kra 0x25 altgr inhibit
+#
+# Scan Code 39
+lstroke 0x26 altgr inhibit
+#
+# Scan Code 46
+guillemotleft 0x2c altgr inhibit
+#
+# Scan Code 47
+guillemotright 0x2d altgr inhibit
+#
+# Scan Code 49
+leftdoublequotemark 0x2f altgr inhibit
+#
+# Scan Code 50
+rightdoublequotemark 0x30 altgr inhibit
+#
+# Scan Code 52
+mu 0x32 altgr inhibit
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/he
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/he	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/he	(revision 55121)
@@ -0,0 +1,91 @@
+# Generated by Shlomil
+# Please send your comments and corrections to <shlomister@gmail.com>
+include common
+map 0x040D
+
+
+#
+# Top row
+#
+
+slash 0x10 altgr
+apostrophe 0x11 altgr
+hebrew_qoph 0x12 altgr
+hebrew_resh 0x13 altgr
+hebrew_aleph 0x14 altgr
+hebrew_tet 0x15 altgr
+hebrew_waw 0x16 altgr
+hebrew_finalnun 0x17 altgr
+hebrew_finalmem 0x18 altgr
+hebrew_pe 0x19 altgr
+
+#
+# Second row
+#
+
+hebrew_shin 0x1e altgr
+hebrew_dalet 0x1f altgr
+hebrew_gimel 0x20 altgr
+hebrew_kaph 0x21 altgr
+hebrew_ayin 0x22 altgr
+hebrew_yod 0x23 altgr
+hebrew_chet 0x24 altgr
+hebrew_lamed 0x25 altgr
+hebrew_finalkaph 0x26 altgr
+hebrew_finalpe 0x27 altgr
+comma 0x28 altgr
+
+#
+# Third row
+#
+
+hebrew_zain 0x2c altgr
+hebrew_samech 0x2d altgr
+hebrew_bet 0x2e altgr
+hebrew_he 0x2f altgr
+hebrew_nun 0x30 altgr
+hebrew_mem 0x31 altgr
+hebrew_zade 0x32 altgr
+
+hebrew_taw 0x33 altgr
+hebrew_finalzade 0x34 altgr
+period 0x35 altgr
+
+
+#
+# en-us
+#
+
+
+exclam 0x02 shift
+at 0x03 shift
+numbersign 0x04 shift
+dollar 0x05 shift
+percent 0x06 shift
+asciicircum 0x07 shift
+ampersand 0x08 shift
+asterisk 0x09 shift
+parenleft 0x0a shift
+parenright 0x0b shift
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+bracketleft 0x1a
+braceleft 0x1a shift
+bracketright 0x1b
+braceright 0x1b shift
+semicolon 0x27
+colon 0x27 shift
+apostrophe 0x28
+quotedbl 0x28 shift
+grave 0x29
+asciitilde 0x29 shift
+backslash 0x2b
+bar 0x2b shift
+comma 0x33
+less 0x33 shift
+period 0x34
+greater 0x34 shift
+slash 0x35
+question 0x35 shift
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/hr
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/hr	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/hr	(revision 55121)
@@ -0,0 +1,125 @@
+# generated from XKB map hr
+include common
+map 0x41a
+exclam 0x02 shift
+asciitilde 0x02 altgr
+dead_tilde 0x02 shift altgr
+quotedbl 0x03 shift
+dead_caron 0x03 altgr
+caron 0x03 shift altgr
+numbersign 0x04 shift
+asciicircum 0x04 altgr
+dead_circumflex 0x04 shift altgr
+dollar 0x05 shift
+dead_breve 0x05 altgr
+breve 0x05 shift altgr
+percent 0x06 shift
+degree 0x06 altgr
+dead_abovering 0x06 shift altgr
+ampersand 0x07 shift
+dead_ogonek 0x07 altgr
+ogonek 0x07 shift altgr
+slash 0x08 shift
+grave 0x08 altgr
+dead_grave 0x08 shift altgr
+parenleft 0x09 shift
+dead_abovedot 0x09 altgr
+abovedot 0x09 shift altgr
+parenright 0x0a shift
+dead_acute 0x0a altgr
+apostrophe 0x0a shift altgr
+equal 0x0b shift
+dead_doubleacute 0x0b altgr
+doubleacute 0x0b shift altgr
+apostrophe 0x0c
+question 0x0c shift
+dead_diaeresis 0x0c altgr
+diaeresis 0x0c shift altgr
+plus 0x0d
+asterisk 0x0d shift
+dead_cedilla 0x0d altgr
+cedilla 0x0d shift altgr
+backslash 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+bar 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+z 0x15 addupper
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+scaron 0x1a
+Scaron 0x1a shift
+division 0x1a altgr
+dead_abovering 0x1a shift altgr
+dstroke 0x1b
+Dstroke 0x1b shift
+multiply 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+bracketleft 0x21 altgr
+ordfeminine 0x21 shift altgr
+bracketright 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+lstroke 0x25 altgr
+ampersand 0x25 shift altgr
+Lstroke 0x26 altgr
+ccaron 0x27
+Ccaron 0x27 shift
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+cacute 0x28
+Cacute 0x28 shift
+ssharp 0x28 altgr
+dead_caron 0x28 shift altgr
+dead_cedilla 0x29
+dead_diaeresis 0x29 shift
+notsign 0x29 altgr
+zcaron 0x2b
+Zcaron 0x2b shift
+currency 0x2b altgr
+dead_breve 0x2b shift altgr
+y 0x2c addupper
+guillemotleft 0x2c altgr
+less 0x2c shift altgr
+guillemotright 0x2d altgr
+greater 0x2d shift altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+at 0x2f altgr
+grave 0x2f shift altgr
+braceleft 0x30 altgr
+apostrophe 0x30 shift altgr
+braceright 0x31 altgr
+section 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/hu
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/hu	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/hu	(revision 55121)
@@ -0,0 +1,115 @@
+# Hungarian keyboard layout (QWERTZ)
+# Created by: The NeverGone <never@delfin.klte.hu>
+
+include common
+map 0x40e
+
+
+# AltGr keys:
+notsign 0x29 altgr
+asciitilde 0x02 altgr
+caron 0x03 altgr
+asciicircum 0x04 altgr
+breve 0x05 altgr
+degree 0x06 altgr
+ogonek 0x07 altgr
+grave 0x08 altgr
+abovedot 0x09 altgr
+acute 0x0a altgr
+doubleacute 0x0b altgr
+diaeresis 0x0c altgr
+cedilla 0x0d altgr
+backslash 0x10 altgr
+bar 0x11 altgr
+EuroSign 0x12 altgr
+Iacute 0x17 altgr
+division 0x1a altgr
+multiply 0x1b altgr
+dstroke 0x1f altgr
+Dstroke 0x20 altgr
+bracketleft 0x21 altgr
+bracketright 0x22 altgr
+iacute 0x24 altgr
+lstroke 0x25 altgr
+Lstroke 0x26 altgr
+dollar 0x27 altgr
+ssharp 0x28 altgr
+currency 0x2b altgr
+less 0x56 altgr
+greater 0x2c altgr
+numbersign 0x2d altgr
+ampersand 0x2e altgr
+at 0x2f altgr
+braceleft 0x30 altgr
+braceright 0x31 altgr
+semicolon 0x33 altgr
+asterisk 0x35 altgr
+
+
+# Shift keys:
+section 0x29 shift
+apostrophe 0x02 shift
+quotedbl 0x03 shift
+plus 0x04 shift
+exclam 0x05 shift
+percent 0x06 shift
+slash 0x07 shift
+equal 0x08 shift
+parenleft 0x09 shift
+parenright 0x0a shift
+Odiaeresis 0x0b shift
+Udiaeresis 0x0c shift
+Oacute 0x0d shift
+Z 0x15 shift
+Odoubleacute 0x1a shift
+Uacute 0x1b shift
+Eacute 0x27 shift
+Aacute 0x28 shift
+Udoubleacute 0x2b shift
+Y 0x2c shift
+question 0x33 shift
+colon 0x34 shift
+underscore 0x35 shift
+F13 0x3b shift
+F14 0x3c shift
+F15 0x3d shift
+F16 0x3e shift
+F17 0x3f shift
+F18 0x40 shift
+F19 0x41 shift
+F20 0x42 shift
+F21 0x43 shift
+F22 0x44 shift
+F23 0x57 shift
+F24 0x58 shift
+
+
+# Ctrl keys:
+F25 0x3b ctrl
+F26 0x3c ctrl
+F27 0x3d ctrl
+F28 0x3e ctrl
+F29 0x3f ctrl
+F30 0x40 ctrl
+F31 0x41 ctrl
+F32 0x42 ctrl
+F33 0x43 ctrl
+F34 0x44 ctrl
+F35 0x57 ctrl
+#NoSymbol 0x58 ctrl
+
+
+0 0x29
+odiaeresis 0x0b
+udiaeresis 0x0c
+oacute 0x0d
+z 0x15
+odoubleacute 0x1a
+uacute 0x1b
+eacute 0x27
+aacute 0x28
+udoubleacute 0x2b
+y 0x2c
+comma 0x33
+period 0x34
+minus 0x35
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/is
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/is	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/is	(revision 55121)
@@ -0,0 +1,140 @@
+# 2004-03-16 Halldór Guðmundsson and Morten Lange 
+# Keyboard definition file for the Icelandic keyboard
+# to be used in rdesktop 1.3.x ( See rdesktop.org) 
+# generated from XKB map de, and changed manually
+# Location for example /usr/local/share/rdesktop/keymaps/is
+include common
+map 0x40f
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+quotedbl 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+#section 0x04 shift
+numbersign 0x04 shift
+threesuperior 0x04 altgr
+sterling 0x04 shift altgr
+dollar 0x05 shift
+onequarter 0x05 altgr
+currency 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+#ssharp 0x0c
+odiaeresis 0x0c
+#question 0x0c shift
+Odiaeresis 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+#acute 0x0d
+minus  0x0d
+#dead_acute 0x0d
+#grave 0x0d shift
+#dead_grave 0x0d shift
+underscore 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+#z 0x15 addupper
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+#thorn 0x19 altgr
+#THORN 0x19 shift altgr
+#udiaeresis 0x1a
+#Udiaeresis 0x1a shift
+#dead_diaeresis 0x1a altgr
+#dead_abovering 0x1a shift altgr
+eth 0x1a 
+ETH 0x1a shift 
+apostrophe 0x1b
+question 0x1b shift
+#plus 0x1b
+#asterisk 0x1b shift
+asciitilde 0x1b altgr
+#grave 0x1b altgr
+#dead_tilde 0x1b altgr
+#dead_macron 0x1b shift altgr
+#ae 0x1e altgr
+#AE 0x1e shift altgr
+#eth 0x20 altgr
+#eth 0x20 
+#ETH 0x20 shift altgr
+#ETH 0x20 shift 
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+#adiaeresis 0x27
+#Adiaeresis 0x27 shift
+ae 0x27 
+AE 0x27 shift 
+dead_doubleacute 0x27 altgr
+#adiaeresis 0x28
+#Adiaeresis 0x28 shift
+#dead_caron 0x28 shift altgr
+#asciicircum 0x29
+acute  0x28
+dead_acute 0x28
+#dead_circumflex 0x29
+#degree 0x29 shift
+#notsign 0x29 altgr
+plus 0x2b
+asterisk 0x2b shift
+grave 0x2b altgr
+#numbersign 0x2b
+#apostrophe 0x2b shift
+#dead_breve 0x2b shift altgr
+#y 0x2c addupper
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+#minus 0x35
+#underscore 0x35 shift
+thorn 0x35 
+THORN 0x35 shift 
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
+
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/it
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/it	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/it	(revision 55121)
@@ -0,0 +1,113 @@
+# generated from XKB map it
+include common
+map 0x410
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+quotedbl 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+sterling 0x04 shift
+threesuperior 0x04 altgr
+dollar 0x05 shift
+onequarter 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+trademark 0x09 shift altgr
+parenright 0x0a shift
+plusminus 0x0a shift altgr
+equal 0x0b shift
+degree 0x0b shift altgr
+apostrophe 0x0c
+question 0x0c shift
+grave 0x0c altgr
+questiondown 0x0c shift altgr
+igrave 0x0d
+asciicircum 0x0d shift
+asciitilde 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+egrave 0x1a
+eacute 0x1a shift
+bracketleft 0x1a altgr
+braceleft 0x1a shift altgr
+plus 0x1b
+asterisk 0x1b shift
+bracketright 0x1b altgr
+braceright 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+ograve 0x27
+ccedilla 0x27 shift
+at 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+agrave 0x28
+degree 0x28 shift
+numbersign 0x28 altgr
+backslash 0x29
+bar 0x29 shift
+notsign 0x29 altgr
+ugrave 0x2b
+section 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/ja
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/ja	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/ja	(revision 55121)
@@ -0,0 +1,119 @@
+# generated from XKB map jp106
+# See OADG Technical reference for official scancodes:
+# http://www.oadg.or.jp/tosho/index.htm#techref
+include common
+map 0xe0010411
+keyboard_type 0x7
+keyboard_subtype 0x2
+keyboard_functionkeys 0xc
+exclam 0x02 shift
+kana_NU 0x02 altgr
+quotedbl 0x03 shift
+kana_FU 0x03 altgr
+numbersign 0x04 shift
+kana_A 0x04 altgr
+kana_a 0x04 shift altgr
+dollar 0x05 shift
+kana_U 0x05 altgr
+kana_u 0x05 shift altgr
+percent 0x06 shift
+kana_E 0x06 altgr
+kana_e 0x06 shift altgr
+ampersand 0x07 shift
+kana_O 0x07 altgr
+kana_o 0x07 shift altgr
+apostrophe 0x08 shift
+kana_YA 0x08 altgr
+kana_ya 0x08 shift altgr
+parenleft 0x09 shift
+kana_YU 0x09 altgr
+kana_yu 0x09 shift altgr
+parenright 0x0a shift
+kana_YO 0x0a altgr
+kana_yo 0x0a shift altgr
+asciitilde 0x0b shift
+kana_WA 0x0b altgr
+kana_WO 0x0b shift altgr
+minus 0x0c
+equal 0x0c shift
+kana_HO 0x0c altgr
+asciicircum 0x0d
+asciitilde 0x0d shift
+kana_HE 0x0d altgr
+kana_TA 0x10 altgr
+kana_TE 0x11 altgr
+kana_I 0x12 altgr
+kana_i 0x12 shift altgr
+kana_SU 0x13 altgr
+kana_KA 0x14 altgr
+kana_N 0x15 altgr
+kana_NA 0x16 altgr
+kana_NI 0x17 altgr
+kana_RA 0x18 altgr
+kana_SE 0x19 altgr
+at 0x1a
+grave 0x1a shift
+voicedsound 0x1a altgr
+bracketleft 0x1b
+braceleft 0x1b shift
+semivoicedsound 0x1b altgr
+kana_openingbracket 0x1b shift altgr
+kana_CHI 0x1e altgr
+kana_TO 0x1f altgr
+kana_SHI 0x20 altgr
+kana_HA 0x21 altgr
+kana_KI 0x22 altgr
+kana_KU 0x23 altgr
+kana_MA 0x24 altgr
+kana_NO 0x25 altgr
+kana_RI 0x26 altgr
+semicolon 0x27
+plus 0x27 shift
+kana_RE 0x27 altgr
+colon 0x28
+asterisk 0x28 shift
+kana_KE 0x28 altgr
+Zenkaku_Hankaku 0x29
+Kanji 0x29
+bracketright 0x2b
+braceright 0x2b shift
+kana_MU 0x2b altgr
+kana_closingbracket 0x2b shift altgr
+kana_TSU 0x2c altgr
+kana_tsu 0x2c shift altgr
+kana_SA 0x2d altgr
+kana_SO 0x2e altgr
+kana_HI 0x2f altgr
+kana_KO 0x30 altgr
+kana_MI 0x31 altgr
+kana_MO 0x32 altgr
+comma 0x33
+less 0x33 shift
+kana_NE 0x33 altgr
+kana_comma 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+kana_RU 0x34 altgr
+kana_fullstop 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+kana_ME 0x35 altgr
+kana_conjunctive 0x35 shift altgr
+Execute 0x54 shift
+backslash 0x73
+bar 0x7d shift
+underscore 0x73 shift
+Henkan_Mode 0x79
+Hiragana_Katakana 0x70 localstate
+Katakana 0x70
+Romaji 0x70
+Muhenkan 0x7b
+# Plain [Eisu_toggle/Caps_Lock] should NOT have shift
+Eisu_toggle 0x3a
+# [Eisu_toggle/Caps_Lock] key will generate Caps_Lock keysym 
+# only with shift+capslock stroke. Windows also expect this, so prefix a shift
+Caps_Lock 0x3a shift
+# Windows,Menu
+F13 0xdc
+Menu 0xdd
+#todo: Alt_R+Romaji doesnt romaji the IME (Alt_L+Romaji works)
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/ko
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/ko	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/ko	(revision 55121)
@@ -0,0 +1,37 @@
+# generated from XKB map ko
+include common
+map 0xe0010412
+exclam 0x02 shift
+at 0x03 shift
+numbersign 0x04 shift
+dollar 0x05 shift
+percent 0x06 shift
+asciicircum 0x07 shift
+ampersand 0x08 shift
+asterisk 0x09 shift
+parenleft 0x0a shift
+parenright 0x0b shift
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+bracketleft 0x1a
+braceleft 0x1a shift
+bracketright 0x1b
+braceright 0x1b shift
+semicolon 0x27
+colon 0x27 shift
+apostrophe 0x28
+quotedbl 0x28 shift
+grave 0x29
+asciitilde 0x29 shift
+backslash 0x2b
+bar 0x2b shift
+comma 0x33
+less 0x33 shift
+period 0x34
+greater 0x34 shift
+slash 0x35
+question 0x35 shift
+Hangul 0xf2
+Hangul_Hanja 0xf1
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/lt
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/lt	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/lt	(revision 55121)
@@ -0,0 +1,57 @@
+# generated from XKB map lt
+include common
+map 0x427
+exclam 0x02 shift
+aogonek 0x02 altgr
+Aogonek 0x02 shift altgr
+at 0x03 shift
+ccaron 0x03 altgr
+Ccaron 0x03 shift altgr
+numbersign 0x04 shift
+eogonek 0x04 altgr
+Eogonek 0x04 shift altgr
+dollar 0x05 shift
+eabovedot 0x05 altgr
+Eabovedot 0x05 shift altgr
+percent 0x06 shift
+iogonek 0x06 altgr
+Iogonek 0x06 shift altgr
+asciicircum 0x07 shift
+scaron 0x07 altgr
+Scaron 0x07 shift altgr
+ampersand 0x08 shift
+uogonek 0x08 altgr
+Uogonek 0x08 shift altgr
+asterisk 0x09 shift
+umacron 0x09 altgr
+Umacron 0x09 shift altgr
+parenleft 0x0a shift
+doublelowquotemark 0x0a altgr
+parenright 0x0b shift
+leftdoublequotemark 0x0b altgr
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+zcaron 0x0d altgr
+Zcaron 0x0d shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+bracketright 0x1b
+braceright 0x1b shift
+semicolon 0x27
+colon 0x27 shift
+apostrophe 0x28
+quotedbl 0x28 shift
+grave 0x29
+asciitilde 0x29 shift
+backslash 0x2b
+bar 0x2b shift
+comma 0x33
+less 0x33 shift
+period 0x34
+greater 0x34 shift
+slash 0x35
+question 0x35 shift
+endash 0x56
+EuroSign 0x56 shift
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/lv
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/lv	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/lv	(revision 55121)
@@ -0,0 +1,128 @@
+# generated from XKB map lv
+include common
+map 0x426
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+at 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+numbersign 0x04 shift
+threesuperior 0x04 altgr
+sterling 0x04 shift altgr
+dollar 0x05 shift
+EuroSign 0x05 altgr
+cent 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+asciicircum 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+ampersand 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+asterisk 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenleft 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+parenright 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+minus 0x0c
+underscore 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+equal 0x0d
+plus 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+emacron 0x12 altgr
+Emacron 0x12 shift altgr
+rcedilla 0x13 altgr
+Rcedilla 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+umacron 0x16 altgr
+Umacron 0x16 shift altgr
+imacron 0x17 altgr
+Imacron 0x17 shift altgr
+omacron 0x18 altgr
+Omacron 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+dead_tilde 0x1b altgr
+dead_macron 0x1b shift altgr
+ISO_Next_Group 0x1c shift
+amacron 0x1e altgr
+Amacron 0x1e shift altgr
+scaron 0x1f altgr
+Scaron 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+gcedilla 0x22 altgr
+Gcedilla 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kcedilla 0x25 altgr
+Kcedilla 0x25 shift altgr
+lcedilla 0x26 altgr
+Lcedilla 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+leftdoublequotemark 0x28 altgr
+doublelowquotemark 0x28 shift altgr
+grave 0x29
+asciitilde 0x29 shift
+notsign 0x29 altgr
+backslash 0x2b
+bar 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+zcaron 0x2c altgr
+Zcaron 0x2c shift altgr
+guillemotright 0x2d altgr
+greater 0x2d shift altgr
+ccaron 0x2e altgr
+Ccaron 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+apostrophe 0x30 shift altgr
+ncedilla 0x31 altgr
+Ncedilla 0x31 shift altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
+nobreakspace 0x39 altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/mk
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/mk	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/mk	(revision 55121)
@@ -0,0 +1,101 @@
+# generated from XKB map mk
+include common
+map 0x42f
+exclam 0x02 shift
+at 0x03 shift
+doublelowquotemark 0x03 shift altgr
+numbersign 0x04 shift
+leftdoublequotemark 0x04 shift altgr
+dollar 0x05 shift
+percent 0x06 shift
+asciicircum 0x07 shift
+ampersand 0x08 shift
+asterisk 0x09 shift
+parenleft 0x0a shift
+parenright 0x0b shift
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+Cyrillic_lje 0x10 altgr
+Cyrillic_LJE 0x10 shift altgr
+Cyrillic_nje 0x11 altgr
+Cyrillic_NJE 0x11 shift altgr
+Cyrillic_ie 0x12 altgr
+Cyrillic_IE 0x12 shift altgr
+Cyrillic_er 0x13 altgr
+Cyrillic_ER 0x13 shift altgr
+Cyrillic_te 0x14 altgr
+Cyrillic_TE 0x14 shift altgr
+Macedonia_dse 0x15 altgr
+Macedonia_DSE 0x15 shift altgr
+Cyrillic_u 0x16 altgr
+Cyrillic_U 0x16 shift altgr
+Cyrillic_i 0x17 altgr
+Cyrillic_I 0x17 shift altgr
+Cyrillic_o 0x18 altgr
+Cyrillic_O 0x18 shift altgr
+Cyrillic_pe 0x19 altgr
+Cyrillic_PE 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+Cyrillic_sha 0x1a altgr
+Cyrillic_SHA 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+Macedonia_gje 0x1b altgr
+Macedonia_GJE 0x1b shift altgr
+Cyrillic_a 0x1e altgr
+Cyrillic_A 0x1e shift altgr
+Cyrillic_es 0x1f altgr
+Cyrillic_ES 0x1f shift altgr
+Cyrillic_de 0x20 altgr
+Cyrillic_DE 0x20 shift altgr
+Cyrillic_ef 0x21 altgr
+Cyrillic_EF 0x21 shift altgr
+Cyrillic_ghe 0x22 altgr
+Cyrillic_GHE 0x22 shift altgr
+Cyrillic_ha 0x23 altgr
+Cyrillic_HA 0x23 shift altgr
+Cyrillic_je 0x24 altgr
+Cyrillic_JE 0x24 shift altgr
+Cyrillic_ka 0x25 altgr
+Cyrillic_KA 0x25 shift altgr
+Cyrillic_el 0x26 altgr
+Cyrillic_EL 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+Cyrillic_che 0x27 altgr
+Cyrillic_CHE 0x27 shift altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+Macedonia_kje 0x28 altgr
+Macedonia_KJE 0x28 shift altgr
+grave 0x29
+asciitilde 0x29 shift
+backslash 0x2b
+bar 0x2b shift
+Cyrillic_zhe 0x2b altgr
+Cyrillic_ZHE 0x2b shift altgr
+Cyrillic_ze 0x2c altgr
+Cyrillic_ZE 0x2c shift altgr
+Cyrillic_dzhe 0x2d altgr
+Cyrillic_DZHE 0x2d shift altgr
+Cyrillic_tse 0x2e altgr
+Cyrillic_TSE 0x2e shift altgr
+Cyrillic_ve 0x2f altgr
+Cyrillic_VE 0x2f shift altgr
+Cyrillic_be 0x30 altgr
+Cyrillic_BE 0x30 shift altgr
+Cyrillic_en 0x31 altgr
+Cyrillic_EN 0x31 shift altgr
+Cyrillic_em 0x32 altgr
+Cyrillic_EM 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+semicolon 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+colon 0x34 shift altgr
+slash 0x35
+question 0x35 shift
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/modifiers
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/modifiers	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/modifiers	(revision 55121)
@@ -0,0 +1,18 @@
+Shift_R 0x36
+Shift_L 0x2a
+
+Alt_R 0xb8
+Mode_switch 0xb8
+ISO_Level3_Shift 0xb8
+
+Alt_L 0x38
+
+Control_R 0x9d
+Control_L 0x1d
+
+# Translate Meta, Super and Hyper to Windows keys. 
+# This is hardcoded. See documentation for details. 
+
+# Translate Menu to the Windows Application key. 
+# This one does not work either. 
+Menu 0xdd
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/nl
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/nl	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/nl	(revision 55121)
@@ -0,0 +1,60 @@
+# Dutch (Netherlands)
+include common
+map 0x413
+
+exclam 0x02 shift
+onesuperior 0x02 altgr
+quotebl 0x03 shift
+twosuperior 0x03 altgr
+numbersign 0x04 shift
+threesuperior 0x04 altgr
+dollar 0x05 shift
+onequarter 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+ampersand 0x07 shift
+threequarters 0x07 altgr
+underscore 0x08 shift
+sterling 0x08 altgr
+parenleft 0x09 shift
+braceleft 0x09 altgr
+parenright 0x0a shift
+braceright 0x0a altgr
+apostrophe 0x0b shift
+slash 0x0c
+question 0x0c shift
+backslash 0x0c altgr
+degree 0x0d
+dead_tilde 0x0d shift
+dead_cedilla 0x0d altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+dead_diaeresis 0x1a
+dead_circumflex 0x1a shift
+asterisk 0x1b
+bar 0x1b shift
+ssharp 0x1f altgr
+plus 0x27
+plusminus 0x27 shift
+dead_acute 0x28
+dead_grave 0x28 shift
+at 0x29
+section 0x29 shift
+notsign 0x29 altgr
+less 0x2b
+greater 0x2b shift
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+copyright 0x2e altgr 
+mu 0x32 altgr
+comma 0x33
+semicolon 0x33 shift
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+minus 0x35
+equal 0x35 shift
+bracketright 0x56
+bracketleft 0x56 shift
+brokenbar 0x56 altgr
+
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/nl-be
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/nl-be	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/nl-be	(revision 55121)
@@ -0,0 +1,142 @@
+# Dutch (Belgium)
+map 0x813
+include common
+ampersand 0x02
+1 0x02 shift
+bar 0x02 altgr
+exclamdown 0x02 shift altgr
+eacute 0x03
+2 0x03 shift
+at 0x03 altgr
+oneeighth 0x03 shift altgr
+quotedbl 0x04
+3 0x04 shift
+numbersign 0x04 altgr
+sterling 0x04 shift altgr
+apostrophe 0x05
+4 0x05 shift
+onequarter 0x05 altgr
+dollar 0x05 shift altgr
+parenleft 0x06
+5 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+section 0x07
+6 0x07 shift
+asciicircum 0x07 altgr
+fiveeighths 0x07 shift altgr
+egrave 0x08
+7 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+exclam 0x09
+8 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+ccedilla 0x0a
+9 0x0a shift
+braceleft 0x0a altgr
+plusminus 0x0a shift altgr
+agrave 0x0b
+0 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+parenright 0x0c
+degree 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+minus 0x0d
+underscore 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+a 0x10 addupper
+# at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+z 0x11 addupper
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+dead_circumflex 0x1a
+dead_diaeresis 0x1a shift
+bracketleft 0x1a altgr
+dead_abovering 0x1a shift altgr
+dollar 0x1b
+asterisk 0x1b shift
+bracketright 0x1b altgr
+dead_macron 0x1b shift altgr
+q 0x1e addupper
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+# ampersand 0x25 shift altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+m 0x27 addupper
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+ugrave 0x28
+percent 0x28 shift
+dead_acute 0x28 altgr
+dead_caron 0x28 shift altgr
+twosuperior 0x29
+threesuperior 0x29 shift
+notsign 0x29 altgr
+mu 0x2b
+sterling 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+w 0x2c addupper
+guillemotleft 0x2c altgr
+less 0x2c shift altgr
+guillemotright 0x2d altgr
+greater 0x2d shift altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+# apostrophe 0x30 shift altgr
+comma 0x32
+question 0x32 shift
+dead_cedilla 0x32 altgr
+masculine 0x32 shift altgr
+semicolon 0x33
+period 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+colon 0x34
+slash 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+equal 0x35
+plus 0x35 shift
+dead_tilde 0x35 altgr
+dead_abovedot 0x35 shift altgr
+backslash 0x56 altgr
+less 0x56 
+greater 0x56 shift
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/no
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/no	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/no	(revision 55121)
@@ -0,0 +1,119 @@
+# generated from XKB map no
+include common
+map 0x414
+exclam 0x02 shift
+exclamdown 0x02 altgr
+onesuperior 0x02 shift altgr
+quotedbl 0x03 shift
+at 0x03 altgr
+twosuperior 0x03 shift altgr
+numbersign 0x04 shift
+sterling 0x04 altgr
+threesuperior 0x04 shift altgr
+currency 0x05 shift
+dollar 0x05 altgr
+onequarter 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+cent 0x06 shift altgr
+ampersand 0x07 shift
+yen 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+division 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+guillemotleft 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+guillemotright 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+plus 0x0c
+question 0x0c shift
+plusminus 0x0c altgr
+questiondown 0x0c shift altgr
+backslash 0x0d
+dead_grave 0x0d shift
+dead_acute 0x0d altgr
+notsign 0x0d shift altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+registered 0x13 altgr
+thorn 0x14 altgr
+THORN 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oe 0x18 altgr
+OE 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+aring 0x1a
+Aring 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+dead_diaeresis 0x1b
+dead_circumflex 0x1b shift
+asciicircum 0x01b shift
+dead_tilde 0x1b altgr
+asciitilde 0x1b altgr
+dead_caron 0x1b shift altgr
+ordfeminine 0x1e altgr
+masculine 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+oslash 0x27
+Ooblique 0x27 shift
+dead_doubleacute 0x27 shift altgr
+ae 0x28
+AE 0x28 shift
+dead_caron 0x28 shift altgr
+bar 0x29
+section 0x29 shift
+brokenbar 0x29 altgr
+paragraph 0x29 shift altgr
+apostrophe 0x2b
+asterisk 0x2b shift
+multiply 0x2b shift altgr
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+copyright 0x2e altgr
+leftdoublequotemark 0x2f altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+dead_cedilla 0x33 altgr
+dead_ogonek 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+dead_abovedot 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+hyphen 0x35 altgr
+macron 0x35 shift altgr
+nobreakspace 0x39 altgr
+onehalf 0x56 altgr
+threequarters 0x56 shift altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/pl
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/pl	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/pl	(revision 55121)
@@ -0,0 +1,122 @@
+# generated from XKB map pl
+include common
+map 0x415
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+at 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+numbersign 0x04 shift
+threesuperior 0x04 altgr
+sterling 0x04 shift altgr
+dollar 0x05 shift
+onequarter 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+asciicircum 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+ampersand 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+asterisk 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenleft 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+parenright 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+minus 0x0c
+underscore 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+equal 0x0d
+plus 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+eogonek 0x12 altgr
+Eogonek 0x12 shift altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+EuroSign 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oacute 0x18 altgr
+Oacute 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+dead_tilde 0x1b altgr
+dead_macron 0x1b shift altgr
+aogonek 0x1e altgr
+Aogonek 0x1e shift altgr
+sacute 0x1f altgr
+Sacute 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+dead_circumflex 0x28 altgr
+dead_caron 0x28 shift altgr
+grave 0x29
+asciitilde 0x29 shift
+notsign 0x29 altgr
+backslash 0x2b
+bar 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+zabovedot 0x2c altgr
+Zabovedot 0x2c shift altgr
+zacute 0x2d altgr
+Zacute 0x2d shift altgr
+cacute 0x2e altgr
+Cacute 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+nacute 0x31 altgr
+Nacute 0x31 shift altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/pt
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/pt	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/pt	(revision 55121)
@@ -0,0 +1,113 @@
+# generated from XKB map pt
+include common
+map 0x816
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+quotedbl 0x03 shift
+at 0x03 altgr
+oneeighth 0x03 shift altgr
+numbersign 0x04 shift
+sterling 0x04 altgr
+dollar 0x05 shift
+section 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+apostrophe 0x0c
+question 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+guillemotleft 0x0d
+guillemotright 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+plus 0x1a
+asterisk 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+dead_acute 0x1b
+dead_grave 0x1b shift
+dead_tilde 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+ccedilla 0x27
+Ccedilla 0x27 shift
+dead_doubleacute 0x27 shift altgr
+masculine 0x28
+ordfeminine 0x28 shift
+dead_circumflex 0x28 altgr
+dead_caron 0x28 shift altgr
+backslash 0x29
+bar 0x29 shift
+notsign 0x29 altgr
+dead_tilde 0x2b
+dead_circumflex 0x2b shift
+dead_breve 0x2b shift altgr
+less 0x56
+greater 0x56 shift
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/pt-br
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/pt-br	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/pt-br	(revision 55121)
@@ -0,0 +1,69 @@
+# generated from XKB map br
+include common
+map 0x416
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+at 0x03 shift
+twosuperior 0x03 altgr
+onehalf 0x03 shift altgr
+numbersign 0x04 shift
+threesuperior 0x04 altgr
+threequarters 0x04 shift altgr
+dollar 0x05 shift
+sterling 0x05 altgr
+onequarter 0x05 shift altgr
+percent 0x06 shift
+cent 0x06 altgr
+dead_diaeresis 0x07 shift
+notsign 0x07 altgr
+diaeresis 0x07 shift altgr
+ampersand 0x08 shift
+braceleft 0x08 altgr
+asterisk 0x09 shift
+bracketleft 0x09 altgr
+parenleft 0x0a shift
+bracketright 0x0a altgr
+parenright 0x0b shift
+braceright 0x0b altgr
+minus 0x0c
+underscore 0x0c shift
+backslash 0x0c altgr
+equal 0x0d
+plus 0x0d shift
+section 0x0d altgr
+EuroSign 0x12 altgr
+registered 0x13 altgr
+dead_acute 0x1a
+dead_grave 0x1a shift
+acute 0x1a altgr
+grave 0x1a shift altgr
+bracketleft 0x1b
+braceleft 0x1b shift
+ordfeminine 0x1b altgr
+ccedilla 0x27
+Ccedilla 0x27 shift
+dead_tilde 0x28
+dead_circumflex 0x28 shift
+asciitilde 0x28 altgr
+asciicircum 0x28 shift altgr
+apostrophe 0x29
+quotedbl 0x29 shift
+bracketright 0x2b
+braceright 0x2b shift
+masculine 0x2b altgr
+copyright 0x2e altgr
+mu 0x32 altgr
+comma 0x33
+less 0x33 shift
+period 0x34
+greater 0x34 shift
+semicolon 0x35
+colon 0x35 shift
+comma 0x53 numlock
+backslash 0x56
+bar 0x56 shift
+slash 0x73
+question 0x73 shift
+degree 0x73 altgr
+KP_Decimal 0x34
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/ru
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/ru	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/ru	(revision 55121)
@@ -0,0 +1,109 @@
+# generated from XKB map ru
+include common
+map 0x419
+exclam 0x02 shift
+at 0x03 shift
+quotedbl 0x03 shift altgr
+numbersign 0x04 shift
+dollar 0x05 shift
+asterisk 0x05 shift altgr
+percent 0x06 shift
+colon 0x06 shift altgr
+asciicircum 0x07 shift
+comma 0x07 shift altgr
+ampersand 0x08 shift
+period 0x08 shift altgr
+asterisk 0x09 shift
+semicolon 0x09 shift altgr
+parenleft 0x0a shift
+parenright 0x0b shift
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+Cyrillic_shorti 0x10 altgr
+Cyrillic_SHORTI 0x10 shift altgr
+Cyrillic_tse 0x11 altgr
+Cyrillic_TSE 0x11 shift altgr
+Cyrillic_u 0x12 altgr
+Cyrillic_U 0x12 shift altgr
+Cyrillic_ka 0x13 altgr
+Cyrillic_KA 0x13 shift altgr
+Cyrillic_ie 0x14 altgr
+Cyrillic_IE 0x14 shift altgr
+Cyrillic_en 0x15 altgr
+Cyrillic_EN 0x15 shift altgr
+Cyrillic_ghe 0x16 altgr
+Cyrillic_GHE 0x16 shift altgr
+Cyrillic_sha 0x17 altgr
+Cyrillic_SHA 0x17 shift altgr
+Cyrillic_shcha 0x18 altgr
+Cyrillic_SHCHA 0x18 shift altgr
+Cyrillic_ze 0x19 altgr
+Cyrillic_ZE 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+Cyrillic_ha 0x1a altgr
+Cyrillic_HA 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+Cyrillic_hardsign 0x1b altgr
+Cyrillic_HARDSIGN 0x1b shift altgr
+Cyrillic_ef 0x1e altgr
+Cyrillic_EF 0x1e shift altgr
+Cyrillic_yeru 0x1f altgr
+Cyrillic_YERU 0x1f shift altgr
+Cyrillic_ve 0x20 altgr
+Cyrillic_VE 0x20 shift altgr
+Cyrillic_a 0x21 altgr
+Cyrillic_A 0x21 shift altgr
+Cyrillic_pe 0x22 altgr
+Cyrillic_PE 0x22 shift altgr
+Cyrillic_er 0x23 altgr
+Cyrillic_ER 0x23 shift altgr
+Cyrillic_o 0x24 altgr
+Cyrillic_O 0x24 shift altgr
+Cyrillic_el 0x25 altgr
+Cyrillic_EL 0x25 shift altgr
+Cyrillic_de 0x26 altgr
+Cyrillic_DE 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+Cyrillic_zhe 0x27 altgr
+Cyrillic_ZHE 0x27 shift altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+Cyrillic_e 0x28 altgr
+Cyrillic_E 0x28 shift altgr
+grave 0x29
+asciitilde 0x29 shift
+Cyrillic_io 0x29 altgr
+Cyrillic_IO 0x29 shift altgr
+backslash 0x2b
+bar 0x2b shift
+Cyrillic_ya 0x2c altgr
+Cyrillic_YA 0x2c shift altgr
+Cyrillic_che 0x2d altgr
+Cyrillic_CHE 0x2d shift altgr
+Cyrillic_es 0x2e altgr
+Cyrillic_ES 0x2e shift altgr
+Cyrillic_em 0x2f altgr
+Cyrillic_EM 0x2f shift altgr
+Cyrillic_i 0x30 altgr
+Cyrillic_I 0x30 shift altgr
+Cyrillic_te 0x31 altgr
+Cyrillic_TE 0x31 shift altgr
+Cyrillic_softsign 0x32 altgr
+Cyrillic_SOFTSIGN 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+Cyrillic_be 0x33 altgr
+Cyrillic_BE 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+Cyrillic_yu 0x34 altgr
+Cyrillic_YU 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+slash 0x56 altgr
+bar 0x56 shift altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/sk
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/sk	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/sk	(revision 55121)
@@ -0,0 +1,189 @@
+#Slovak keymap
+#2007-05-28 by Jaroslav Jiricka <giahra@atlas.cz>
+include common
+
+#Additional sequences
+#2007-05-28 by Jaroslav Jiricka <giahra@atlas.cz>
+
+sequence ecaron dead_caron e
+sequence Ecaron dead_caron E
+sequence eogonek dead_ogonek e
+sequence Eogonek dead_ogonek E
+
+sequence rcaron dead_caron r
+sequence Rcaron dead_caron R
+sequence racute dead_acute r
+sequence Racute dead_acute R
+
+sequence tcaron dead_caron t
+sequence Tcaron dead_caron T
+sequence tcedilla dead_cedilla t
+sequence Tcedilla dead_cedilla T
+
+sequence zcaron dead_caron z
+sequence Zcaron dead_caron Z
+sequence zacute dead_acute z
+sequence Zacute dead_acute Z
+sequence zabovedot dead_abovedot z
+sequence Zabovedot dead_abovedot Z
+
+sequence uring dead_abovering u
+sequence Uring dead_abovering U
+sequence udoubleacute dead_doubleacute u
+sequence Udoubleacute dead_doubleacute U
+
+sequence odoubleacute dead_doubleacute o
+sequence Odoubleacute dead_doubleacute O
+
+sequence aogonek dead_ogonek a
+sequence Aogonek dead_ogonek A
+sequence abreve dead_breve a
+sequence Abreve dead_breve A
+
+sequence scaron dead_caron s
+sequence Scaron dead_caron S
+sequence sacute dead_acute s
+sequence Sacute dead_acute S
+sequence scedilla dead_cedilla s
+sequence Scedilla dead_cedilla S
+
+sequence dcaron dead_caron d
+sequence Dcaron dead_caron D
+
+sequence gbreve dead_breve g
+sequence Gbreve dead_breve G
+
+sequence lcaron dead_caron l
+sequence Lcaron dead_caron L
+sequence lacute dead_acute l
+sequence Lacute dead_acute L
+
+sequence ccaron dead_caron c
+sequence Ccaron dead_caron C
+
+sequence ncaron dead_caron n
+sequence Ncaron dead_caron N
+sequence nacute dead_acute n
+sequence Nacute dead_acute N
+#Additional sequences end
+
+map 0x41B
+
+semicolon 0x29
+dead_abovering 0x29 shift
+
+plus 0x02
+1 0x02 shift
+dead_tilde 0x02 altgr
+asciitilde 0x02 altgr
+
+lcaron 0x03
+2 0x03 shift
+dead_caron 0x03 altgr
+
+scaron 0x04
+3 0x04 shift
+dead_circumflex 0x04 altgr
+
+ccaron 0x05
+4 0x05 shift
+dead_breve 0x05 altgr
+
+tcaron 0x06
+5 0x06 shift
+dead_abovering 0x06 altgr
+
+zcaron 0x07
+6 0x07 shift
+dead_ogonek 0x07 altgr
+
+yacute 0x08
+7 0x08 shift
+dead_grave 0x08 altgr
+
+aacute 0x09
+8 0x09 shift
+dead_abovedot 0x08 altgr
+
+iacute 0x0a
+9 0x0a shift
+dead_acute 0x08 altgr
+
+eacute 0x0b
+0 0x0b shift
+dead_doubleacute 0x0b altgr
+
+equal 0x0c
+percent 0x0c shift
+dead_diaeresis 0x0c altgr
+
+dead_acute 0x0d
+dead_caron 0x0d shift
+dead_cedilla 0x0d altgr
+
+backslash 0x10 altgr
+
+bar 0x11 altgr
+
+EuroSign 0x12 altgr
+
+z 0x15 addupper
+
+apostrophe 0x19 altgr
+
+uacute 0x1a
+slash 0x1a shift
+division 0x1a altgr
+
+adiaeresis 0x1b
+parenleft 0x1b shift
+multiply 0x1b altgr
+
+ncaron 0x2b
+parenright 0x2b shift
+currency 0x2b altgr
+
+dstroke 0x1f altgr
+
+Dstroke 0x20 altgr
+
+bracketleft 0x21 altgr
+
+bracketright 0x22 altgr
+
+lstroke 0x25 altgr
+
+Lstroke 0x26 altgr
+
+ocircumflex 0x27
+quotedbl 0x27 shift
+dollar 0x27 altgr
+
+section 0x28
+exclam 0x28 shift
+ssharp 0x28 altgr
+
+y 0x2c addupper
+
+numbersign 0x2d altgr
+
+ampersand 0x2e altgr
+
+at 0x2f altgr
+
+braceleft 0x30 altgr
+
+braceright 0x31 altgr
+
+comma 0x33
+question 0x33 shift
+less 0x33 altgr
+
+period 0x34
+colon 0x34 shift
+greater 0x34 altgr
+
+minus 0x35
+underscore 0x35 shift
+asterisk 0x35 altgr
+
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/sl
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/sl	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/sl	(revision 55121)
@@ -0,0 +1,110 @@
+# generated from XKB map sl
+include common
+map 0x424
+exclam 0x02 shift
+asciitilde 0x02 altgr
+dead_tilde 0x02 shift altgr
+quotedbl 0x03 shift
+dead_caron 0x03 altgr
+caron 0x03 shift altgr
+numbersign 0x04 shift
+asciicircum 0x04 altgr
+dead_circumflex 0x04 shift altgr
+dollar 0x05 shift
+dead_breve 0x05 altgr
+breve 0x05 shift altgr
+percent 0x06 shift
+degree 0x06 altgr
+dead_abovering 0x06 shift altgr
+ampersand 0x07 shift
+dead_ogonek 0x07 altgr
+ogonek 0x07 shift altgr
+slash 0x08 shift
+grave 0x08 altgr
+dead_grave 0x08 shift altgr
+parenleft 0x09 shift
+dead_abovedot 0x09 altgr
+abovedot 0x09 shift altgr
+parenright 0x0a shift
+dead_acute 0x0a altgr
+equal 0x0b shift
+dead_doubleacute 0x0b altgr
+doubleacute 0x0b shift altgr
+apostrophe 0x0c
+question 0x0c shift
+dead_diaeresis 0x0c altgr
+diaeresis 0x0c shift altgr
+plus 0x0d
+asterisk 0x0d shift
+dead_cedilla 0x0d altgr
+cedilla 0x0d shift altgr
+backslash 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+bar 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+z 0x15 addupper
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+scaron 0x1a
+Scaron 0x1a shift
+division 0x1a altgr
+dstroke 0x1b
+Dstroke 0x1b shift
+multiply 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+bracketleft 0x21 altgr
+ordfeminine 0x21 shift altgr
+bracketright 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+lstroke 0x25 altgr
+Lstroke 0x26 altgr
+ccaron 0x27
+Ccaron 0x27 shift
+cacute 0x28
+Cacute 0x28 shift
+ssharp 0x28 altgr
+dead_cedilla 0x29
+notsign 0x29 altgr
+zcaron 0x2b
+Zcaron 0x2b shift
+currency 0x2b altgr
+y 0x2c addupper
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+at 0x2f altgr
+braceleft 0x30 altgr
+braceright 0x31 altgr
+section 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/sv
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/sv	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/sv	(revision 55121)
@@ -0,0 +1,80 @@
+map 0x0000041d
+include common
+
+#
+# Top row
+#
+section 0x29
+onehalf 0x29 shift
+
+# 1
+exclam 0x2 shift
+
+# 2
+quotedbl 0x3 shift
+at 0x3 altgr
+
+# 3
+numbersign 0x4 shift
+sterling 0x4 altgr
+# 4
+currency 0x5 shift
+dollar 0x5 altgr
+# 5
+percent 0x6 shift
+# 6
+ampersand 0x7 shift
+# 7
+slash 0x8 shift
+braceleft 0x8 altgr
+# 8
+parenleft 0x9 shift
+bracketleft 0x9 altgr
+# 9
+parenright 0xa shift
+bracketright 0xa altgr
+# 0
+equal 0xb shift
+braceright 0xb altgr
+
+plus 0xc
+question 0xc shift
+backslash 0xc altgr
+
+dead_acute 0xd
+dead_grave 0xd shift
+
+#
+# QWERTY first row
+#
+EuroSign 0x12 altgr
+aring 0x1a 
+Aring 0x1a shift
+dead_diaeresis 0x1b 
+dead_circumflex 0x1b shift
+dead_tilde 0x1b altgr
+
+#
+# QWERTY second row
+#
+odiaeresis 0x27 
+Odiaeresis 0x27 shift
+adiaeresis 0x28 
+Adiaeresis 0x28 shift
+apostrophe 0x2b
+asterisk 0x2b shift
+
+#
+# QWERTY third row
+#
+less 0x56
+greater 0x56 shift
+bar 0x56 altgr
+mu 0x32 altgr
+comma 0x33
+semicolon 0x33 shift
+period 0x34
+colon 0x34 shift
+minus 0x35
+underscore 0x35 shift
+
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/th
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/th	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/th	(revision 55121)
@@ -0,0 +1,131 @@
+# generated from XKB map th
+include common
+map 0x41e
+exclam 0x02 shift
+Thai_lakkhangyao 0x02 altgr
+plus 0x02 shift altgr
+at 0x03 shift
+slash 0x03 altgr
+Thai_leknung 0x03 shift altgr
+numbersign 0x04 shift
+minus 0x04 altgr
+Thai_leksong 0x04 shift altgr
+dollar 0x05 shift
+Thai_phosamphao 0x05 altgr
+Thai_leksam 0x05 shift altgr
+percent 0x06 shift
+Thai_thothung 0x06 altgr
+Thai_leksi 0x06 shift altgr
+asciicircum 0x07 shift
+Thai_sarau 0x07 altgr
+Thai_sarauu 0x07 shift altgr
+ampersand 0x08 shift
+Thai_saraue 0x08 altgr
+Thai_baht 0x08 shift altgr
+asterisk 0x09 shift
+Thai_khokhwai 0x09 altgr
+Thai_lekha 0x09 shift altgr
+parenleft 0x0a shift
+Thai_totao 0x0a altgr
+Thai_lekhok 0x0a shift altgr
+parenright 0x0b shift
+Thai_chochan 0x0b altgr
+Thai_lekchet 0x0b shift altgr
+minus 0x0c
+underscore 0x0c shift
+Thai_khokhai 0x0c altgr
+Thai_lekpaet 0x0c shift altgr
+equal 0x0d
+plus 0x0d shift
+Thai_chochang 0x0d altgr
+Thai_lekkao 0x0d shift altgr
+Thai_maiyamok 0x10 altgr
+Thai_leksun 0x10 shift altgr
+Thai_saraaimaimalai 0x11 altgr
+quotedbl 0x11 shift altgr
+Thai_saraam 0x12 altgr
+Thai_dochada 0x12 shift altgr
+Thai_phophan 0x13 altgr
+Thai_thonangmontho 0x13 shift altgr
+Thai_saraa 0x14 altgr
+Thai_thothong 0x14 shift altgr
+Thai_maihanakat 0x15 altgr
+Thai_nikhahit 0x15 shift altgr
+Thai_saraii 0x16 altgr
+Thai_maitri 0x16 shift altgr
+Thai_rorua 0x17 altgr
+Thai_nonen 0x17 shift altgr
+Thai_nonu 0x18 altgr
+Thai_paiyannoi 0x18 shift altgr
+Thai_yoyak 0x19 altgr
+Thai_yoying 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+Thai_bobaimai 0x1a altgr
+Thai_thothan 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+Thai_loling 0x1b altgr
+comma 0x1b shift altgr
+Thai_fofan 0x1e altgr
+Thai_ru 0x1e shift altgr
+Thai_hohip 0x1f altgr
+Thai_khorakhang 0x1f shift altgr
+Thai_kokai 0x20 altgr
+Thai_topatak 0x20 shift altgr
+Thai_dodek 0x21 altgr
+Thai_sarao 0x21 shift altgr
+Thai_sarae 0x22 altgr
+Thai_chochoe 0x22 shift altgr
+Thai_maitho 0x23 altgr
+Thai_maitaikhu 0x23 shift altgr
+Thai_maiek 0x24 altgr
+Thai_maichattawa 0x24 shift altgr
+Thai_saraaa 0x25 altgr
+Thai_sorusi 0x25 shift altgr
+Thai_sosua 0x26 altgr
+Thai_sosala 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+Thai_wowaen 0x27 altgr
+Thai_soso 0x27 shift altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+Thai_ngongu 0x28 altgr
+period 0x28 shift altgr
+grave 0x29
+asciitilde 0x29 shift
+underscore 0x29 altgr
+percent 0x29 shift altgr
+ISO_First_Group 0x2a shift
+backslash 0x2b
+bar 0x2b shift
+Thai_khokhuat 0x2b altgr
+Thai_khokhon 0x2b shift altgr
+Thai_phophung 0x2c altgr
+parenleft 0x2c shift altgr
+Thai_popla 0x2d altgr
+parenright 0x2d shift altgr
+Thai_saraae 0x2e altgr
+Thai_choching 0x2e shift altgr
+Thai_oang 0x2f altgr
+Thai_honokhuk 0x2f shift altgr
+Thai_sarai 0x30 altgr
+Thai_phinthu 0x30 shift altgr
+Thai_sarauee 0x31 altgr
+Thai_thanthakhat 0x31 shift altgr
+Thai_thothahan 0x32 altgr
+question 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+Thai_moma 0x33 altgr
+Thai_thophuthao 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+Thai_saraaimaimuan 0x34 altgr
+Thai_lochula 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+Thai_fofa 0x35 altgr
+Thai_lu 0x35 shift altgr
+ISO_Last_Group 0x36 shift
Index: /trunk/src/VBox/RDP/client-1.8.3/keymaps/tr
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/keymaps/tr	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/keymaps/tr	(revision 55121)
@@ -0,0 +1,138 @@
+# rdesktop Turkish Q Keyboard Layout
+#
+# Modified by Umit Oztosun <umit@liqia.com> 20040328
+#
+# Modified from the original mapping file provided with rdesktop 1.3.1.
+# This version works correctly with the right X settings.
+
+include common
+map 0x41f
+
+# First row
+quotedbl 0x29
+eacute 0x29 shift
+backslash 0x29 altgr
+
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+
+apostrophe 0x03 shift
+sterling 0x03 altgr
+twosuperior 0x03 shift altgr
+
+dead_circumflex 0x04 shift
+numbersign 0x04 altgr
+threesuperior 0x04 shift altgr
+
+plus 0x05 shift
+dollar 0x05 altgr
+onequarter 0x05 shift altgr
+
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+
+ampersand 0x07 shift
+threequarters 0x07 altgr
+
+slash 0x08 shift
+braceleft 0x08 altgr
+
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+
+parenright 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+
+equal 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+
+asterisk 0x0c
+question 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+
+minus 0x0d
+underscore 0x0d shift
+division 0x0d altgr
+
+at 0x10 altgr
+
+EuroSign 0x12 altgr
+
+trademark 0x14 altgr
+
+ucircumflex 0x16 altgr
+Ucircumflex 0x16 shift altgr
+
+idotless 0x17
+I 0x17 shift
+icircumflex 0x17 altgr
+Icircumflex 0x17 altgr shift
+
+ocircumflex 0x18 altgr
+Ocircumflex 0x18 shift altgr
+
+gbreve 0x1a
+Gbreve 0x1a shift
+
+udiaeresis 0x1b
+Udiaeresis 0x1b shift
+asciitilde 0x1b altgr
+dead_macron 0x1b shift altgr
+
+comma 0x2b
+semicolon 0x2b shift
+grave 0x2b altgr
+dead_grave 0x2b altgr shift
+
+# Second row
+
+acircumflex 0x1e altgr
+Acircumflex 0x1e shift altgr
+
+section 0x1f altgr
+
+ordfeminine 0x21 altgr
+
+scedilla 0x27
+Scedilla 0x27 shift
+acute 0x27 altgr
+dead_acute 0x27 shift altgr
+
+i 0x28
+Iabovedot 0x28 shift
+dead_caron 0x28 shift altgr
+
+less 0x56
+greater 0x56 shift
+bar 0x56 altgr
+brokenbar 0x56 shift altgr
+
+cent 0x2e altgr
+copyright 0x2e shift altgr
+
+leftdoublequotemark 0x2f altgr
+
+rightdoublequotemark 0x30 altgr
+
+mu 0x32 altgr
+masculine 0x32 shift altgr
+
+odiaeresis 0x33
+Odiaeresis 0x33 shift
+multiply 0x33 altgr
+
+ccedilla 0x34
+Ccedilla 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+
+period 0x35
+colon 0x35 shift
+dead_abovedot 0x35 altgr
+dead_abovedot 0x35 shift altgr
+
Index: /trunk/src/VBox/RDP/client-1.8.3/licence.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/licence.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/licence.c	(revision 55121)
@@ -0,0 +1,387 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   RDP licensing negotiation
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright (C) Thomas Uhle <thomas.uhle@mailbox.tu-dresden.de> 2011
+   Copyright (C) Henrik Andersson <henrik.andersson@cendio.com> 2014
+
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+#include "ssl.h"
+
+extern char *g_username;
+extern char g_hostname[16];
+extern RDP_VERSION g_rdp_version;
+
+static uint8 g_licence_key[16];
+static uint8 g_licence_sign_key[16];
+
+RD_BOOL g_licence_issued = False;
+RD_BOOL g_licence_error_result = False;
+
+/* Generate a session key and RC4 keys, given client and server randoms */
+static void
+licence_generate_keys(uint8 * client_random, uint8 * server_random, uint8 * pre_master_secret)
+{
+	uint8 master_secret[48];
+	uint8 key_block[48];
+
+	/* Generate master secret and then key material */
+	sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
+	sec_hash_48(key_block, master_secret, server_random, client_random, 'A');
+
+	/* Store first 16 bytes of session key as MAC secret */
+	memcpy(g_licence_sign_key, key_block, 16);
+
+	/* Generate RC4 key from next 16 bytes */
+	sec_hash_16(g_licence_key, &key_block[16], client_random, server_random);
+}
+
+static void
+licence_generate_hwid(uint8 * hwid)
+{
+	buf_out_uint32(hwid, 2);
+	strncpy((char *) (hwid + 4), g_hostname, LICENCE_HWID_SIZE - 4);
+}
+
+/* Send a lincece info packet to server */
+static void
+licence_info(uint8 * client_random, uint8 * rsa_data,
+	     uint8 * licence_data, int licence_size, uint8 * hwid, uint8 * signature)
+{
+	uint32 sec_flags = SEC_LICENCE_NEG;
+	uint16 length =
+		24 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE +
+		licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE;
+	STREAM s;
+
+	s = sec_init(sec_flags, length + 2);
+
+	out_uint8(s, LICENCE_TAG_LICENCE_INFO);
+	out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2));	/* version */
+	out_uint16_le(s, length);
+
+	out_uint32_le(s, 1);
+	out_uint16(s, 0);
+	out_uint16_le(s, 0x0201);
+
+	out_uint8p(s, client_random, SEC_RANDOM_SIZE);
+	out_uint16_le(s, 2);
+	out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
+	out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
+	out_uint8s(s, SEC_PADDING_SIZE);
+
+	out_uint16_le(s, 1);
+	out_uint16_le(s, licence_size);
+	out_uint8p(s, licence_data, licence_size);
+
+	out_uint16_le(s, 1);
+	out_uint16_le(s, LICENCE_HWID_SIZE);
+	out_uint8p(s, hwid, LICENCE_HWID_SIZE);
+
+	out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
+
+	s_mark_end(s);
+	sec_send(s, sec_flags);
+}
+
+/* Send a new licence request packet */
+static void
+licence_send_new_licence_request(uint8 * client_random, uint8 * rsa_data, char *user, char *host)
+{
+	uint32 sec_flags = SEC_LICENCE_NEG;
+	uint16 userlen = strlen(user) + 1;
+	uint16 hostlen = strlen(host) + 1;
+	uint16 length =
+		24 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE + userlen + hostlen;
+	STREAM s;
+
+	s = sec_init(sec_flags, length + 2);
+
+	out_uint8(s, LICENCE_TAG_NEW_LICENCE_REQUEST);
+	out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2));	/* version */
+	out_uint16_le(s, length);
+
+	out_uint32_le(s, 1);	// KEY_EXCHANGE_ALG_RSA
+	out_uint16(s, 0);
+	out_uint16_le(s, 0xff01);
+
+	out_uint8p(s, client_random, SEC_RANDOM_SIZE);
+	out_uint16_le(s, 2);
+	out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
+	out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
+	out_uint8s(s, SEC_PADDING_SIZE);
+
+	/* Username LICENSE_BINARY_BLOB */
+	out_uint16_le(s, BB_CLIENT_USER_NAME_BLOB);
+	out_uint16_le(s, userlen);
+	out_uint8p(s, user, userlen);
+
+	/* Machinename LICENSE_BINARY_BLOB */
+	out_uint16_le(s, BB_CLIENT_MACHINE_NAME_BLOB);
+	out_uint16_le(s, hostlen);
+	out_uint8p(s, host, hostlen);
+
+	s_mark_end(s);
+	sec_send(s, sec_flags);
+}
+
+/* Process a licence request packet */
+static void
+licence_process_request(STREAM s)
+{
+	uint8 null_data[SEC_MODULUS_SIZE];
+	uint8 *server_random;
+	uint8 signature[LICENCE_SIGNATURE_SIZE];
+	uint8 hwid[LICENCE_HWID_SIZE];
+	uint8 *licence_data;
+	int licence_size;
+	RDSSL_RC4 crypt_key;
+
+	/* Retrieve the server random from the incoming packet */
+	in_uint8p(s, server_random, SEC_RANDOM_SIZE);
+
+	/* We currently use null client keys. This is a bit naughty but, hey,
+	   the security of licence negotiation isn't exactly paramount. */
+	memset(null_data, 0, sizeof(null_data));
+	licence_generate_keys(null_data, server_random, null_data);
+
+	licence_size = load_licence(&licence_data);
+	if (licence_size > 0)
+	{
+		/* Generate a signature for the HWID buffer */
+		licence_generate_hwid(hwid);
+		sec_sign(signature, 16, g_licence_sign_key, 16, hwid, sizeof(hwid));
+
+		/* Now encrypt the HWID */
+		rdssl_rc4_set_key(&crypt_key, g_licence_key, 16);
+		rdssl_rc4_crypt(&crypt_key, hwid, hwid, sizeof(hwid));
+
+#if WITH_DEBUG
+		DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_LICENCE_INFO));
+#endif
+		licence_info(null_data, null_data, licence_data, licence_size, hwid, signature);
+
+		xfree(licence_data);
+		return;
+	}
+
+#if WITH_DEBUG
+	DEBUG(("Sending licensing PDU (message type 0x%02x)\n", LICENCE_TAG_NEW_LICENCE_REQUEST));
+#endif
+	licence_send_new_licence_request(null_data, null_data, g_username, g_hostname);
+}
+
+/* Send a platform challange response packet */
+static void
+licence_send_platform_challange_response(uint8 * token, uint8 * crypt_hwid, uint8 * signature)
+{
+	uint32 sec_flags = SEC_LICENCE_NEG;
+	uint16 length = 58;
+	STREAM s;
+
+	s = sec_init(sec_flags, length + 2);
+
+	out_uint8(s, LICENCE_TAG_PLATFORM_CHALLANGE_RESPONSE);
+	out_uint8(s, ((g_rdp_version >= RDP_V5) ? 3 : 2));	/* version */
+	out_uint16_le(s, length);
+
+	out_uint16_le(s, 1);
+	out_uint16_le(s, LICENCE_TOKEN_SIZE);
+	out_uint8p(s, token, LICENCE_TOKEN_SIZE);
+
+	out_uint16_le(s, 1);
+	out_uint16_le(s, LICENCE_HWID_SIZE);
+	out_uint8p(s, crypt_hwid, LICENCE_HWID_SIZE);
+
+	out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
+
+	s_mark_end(s);
+	sec_send(s, sec_flags);
+}
+
+/* Parse an platform challange request packet */
+static RD_BOOL
+licence_parse_platform_challange(STREAM s, uint8 ** token, uint8 ** signature)
+{
+	uint16 tokenlen;
+
+	in_uint8s(s, 6);	/* unknown: f8 3d 15 00 04 f6 */
+
+	in_uint16_le(s, tokenlen);
+	if (tokenlen != LICENCE_TOKEN_SIZE)
+	{
+		error("token len %d\n", tokenlen);
+		return False;
+	}
+
+	in_uint8p(s, *token, tokenlen);
+	in_uint8p(s, *signature, LICENCE_SIGNATURE_SIZE);
+
+	return s_check_end(s);
+}
+
+/* Process a platform challange  packet */
+static void
+licence_process_platform_challange(STREAM s)
+{
+	uint8 *in_token = NULL, *in_sig;
+	uint8 out_token[LICENCE_TOKEN_SIZE], decrypt_token[LICENCE_TOKEN_SIZE];
+	uint8 hwid[LICENCE_HWID_SIZE], crypt_hwid[LICENCE_HWID_SIZE];
+	uint8 sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE];
+	uint8 out_sig[LICENCE_SIGNATURE_SIZE];
+	RDSSL_RC4 crypt_key;
+
+	/* Parse incoming packet and save the encrypted token */
+	licence_parse_platform_challange(s, &in_token, &in_sig);
+	memcpy(out_token, in_token, LICENCE_TOKEN_SIZE);
+
+	/* Decrypt the token. It should read TEST in Unicode. */
+	rdssl_rc4_set_key(&crypt_key, g_licence_key, 16);
+	rdssl_rc4_crypt(&crypt_key, in_token, decrypt_token, LICENCE_TOKEN_SIZE);
+
+	/* Generate a signature for a buffer of token and HWID */
+	licence_generate_hwid(hwid);
+	memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE);
+	memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE);
+	sec_sign(out_sig, 16, g_licence_sign_key, 16, sealed_buffer, sizeof(sealed_buffer));
+
+	/* Now encrypt the HWID */
+	rdssl_rc4_set_key(&crypt_key, g_licence_key, 16);
+	rdssl_rc4_crypt(&crypt_key, hwid, crypt_hwid, LICENCE_HWID_SIZE);
+
+	licence_send_platform_challange_response(out_token, crypt_hwid, out_sig);
+}
+
+/* Process a new licence packet */
+static void
+licence_process_new_license(STREAM s)
+{
+	RDSSL_RC4 crypt_key;
+	uint32 length;
+	int i;
+
+	in_uint8s(s, 2);	// Skip license binary blob type
+	in_uint16_le(s, length);
+	if (!s_check_rem(s, length))
+		return;
+
+	rdssl_rc4_set_key(&crypt_key, g_licence_key, 16);
+	rdssl_rc4_crypt(&crypt_key, s->p, s->p, length);
+
+	/* Parse NEW_LICENSE_INFO block */
+	in_uint8s(s, 4);	// skip dwVersion
+
+	/* Skip strings, Scope, CompanyName and ProductId to get
+	   to the LicenseInfo which we store in license blob. */
+	length = 0;
+	for (i = 0; i < 4; i++)
+	{
+		in_uint8s(s, length);
+		in_uint32_le(s, length);
+		if (!s_check_rem(s, length))
+			return;
+	}
+
+	g_licence_issued = True;
+	save_licence(s->p, length);
+}
+
+/* process a licence error alert packet */
+void
+licence_process_error_alert(STREAM s)
+{
+	uint32 error_code;
+	uint32 state_transition;
+	uint32 error_info;
+	in_uint32(s, error_code);
+	in_uint32(s, state_transition);
+	in_uint32(s, error_info);
+
+	/* There is a special case in the error alert handling, when licensing is all good
+	   and the server is not sending a license to client, a "Server License Error PDU -
+	   Valid Client" packet is sent which means, every thing is ok.
+
+	   Therefor we should flag that everything is ok with license here.
+	 */
+	if (error_code == 0x07)
+	{
+		g_licence_issued = True;
+		return;
+	}
+
+	/* handle error codes, for now, jsut report them */
+	switch (error_code)
+	{
+		case 0x6:	// ERR_NO_LICENSE_SERVER
+			warning("License error alert from server: No license server\n");
+			break;
+
+		case 0x8:	// ERR_INVALID_CLIENT
+			warning("License error alert from server: Invalid client\n");
+			break;
+
+		case 0x4:	// ERR_INVALID_SCOPE
+		case 0xb:	// ERR_INVALID_PRODUCTID
+		case 0xc:	// ERR_INVALID_MESSAGE_LENGTH
+		default:
+			warning("License error alert from server: code %u, state transition %u\n",
+				error_code, state_transition);
+			break;
+	}
+
+	g_licence_error_result = True;
+}
+
+
+/* Process a licence packet */
+void
+licence_process(STREAM s)
+{
+	uint8 tag;
+
+	in_uint8(s, tag);
+	in_uint8s(s, 3);	/* version, length */
+
+#if WITH_DEBUG
+	DEBUG(("Received licensing PDU (message type 0x%02x)\n", tag));
+#endif
+
+	switch (tag)
+	{
+		case LICENCE_TAG_REQUEST:
+			licence_process_request(s);
+			break;
+
+		case LICENCE_TAG_PLATFORM_CHALLANGE:
+			licence_process_platform_challange(s);
+			break;
+
+		case LICENCE_TAG_NEW_LICENCE:
+		case LICENCE_TAG_UPGRADE_LICENCE:
+			/* we can handle new and upgrades of licences the same way. */
+			licence_process_new_license(s);
+			break;
+
+		case LICENCE_TAG_ERROR_ALERT:
+			licence_process_error_alert(s);
+			break;
+
+		default:
+			unimpl("licence tag 0x%02x\n", tag);
+	}
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/lspci.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/lspci.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/lspci.c	(revision 55121)
@@ -0,0 +1,176 @@
+/*  -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Support for the Matrox "lspci" channel
+   Copyright (C) 2005 Matrox Graphics Inc. 
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+#include <sys/types.h>
+#include <unistd.h>
+
+static VCHANNEL *lspci_channel;
+
+typedef struct _pci_device
+{
+	uint16 klass;
+	uint16 vendor;
+	uint16 device;
+	uint16 subvendor;
+	uint16 subdevice;
+	uint8 revision;
+	uint8 progif;
+} pci_device;
+
+static pci_device current_device;
+
+static void lspci_send(const char *output);
+
+
+/* Handle one line of output from the lspci subprocess */
+static RD_BOOL
+handle_child_line(const char *line, void *data)
+{
+	const char *val;
+	char buf[1024];
+
+	if (str_startswith(line, "Class:"))
+	{
+		val = line + sizeof("Class:");
+		/* Skip whitespace and second Class: occurance */
+		val += strspn(val, " \t") + sizeof("Class");
+		current_device.klass = strtol(val, NULL, 16);
+	}
+	else if (str_startswith(line, "Vendor:"))
+	{
+		val = line + sizeof("Vendor:");
+		current_device.vendor = strtol(val, NULL, 16);
+	}
+	else if (str_startswith(line, "Device:"))
+	{
+		val = line + sizeof("Device:");
+		/* Sigh, there are *two* lines tagged as Device:. We
+		   are not interested in the domain/bus/slot/func */
+		if (!strchr(val, ':'))
+			current_device.device = strtol(val, NULL, 16);
+	}
+	else if (str_startswith(line, "SVendor:"))
+	{
+		val = line + sizeof("SVendor:");
+		current_device.subvendor = strtol(val, NULL, 16);
+	}
+	else if (str_startswith(line, "SDevice:"))
+	{
+		val = line + sizeof("SDevice:");
+		current_device.subdevice = strtol(val, NULL, 16);
+	}
+	else if (str_startswith(line, "Rev:"))
+	{
+		val = line + sizeof("Rev:");
+		current_device.revision = strtol(val, NULL, 16);
+	}
+	else if (str_startswith(line, "ProgIf:"))
+	{
+		val = line + sizeof("ProgIf:");
+		current_device.progif = strtol(val, NULL, 16);
+	}
+	else if (strspn(line, " \t") == strlen(line))
+	{
+		/* Blank line. Send collected information over channel */
+		snprintf(buf, sizeof(buf), "%04x,%04x,%04x,%04x,%04x,%02x,%02x\n",
+			 current_device.klass, current_device.vendor,
+			 current_device.device, current_device.subvendor,
+			 current_device.subdevice, current_device.revision, current_device.progif);
+		lspci_send(buf);
+		memset(&current_device, 0, sizeof(current_device));
+	}
+	else
+	{
+		warning("lspci: Unrecoqnized line '%s'\n", line);
+	}
+	return True;
+}
+
+
+/* Process one line of input from virtual channel */
+static RD_BOOL
+lspci_process_line(const char *line, void *data)
+{
+	char *lspci_command[5] = { "lspci", "-m", "-n", "-v", NULL };
+
+	if (!strcmp(line, "LSPCI"))
+	{
+		memset(&current_device, 0, sizeof(current_device));
+		subprocess(lspci_command, handle_child_line, NULL);
+		/* Send single dot to indicate end of enumeration */
+		lspci_send(".\n");
+	}
+	else
+	{
+		error("lspci protocol error: Invalid line '%s'\n", line);
+	}
+	return True;
+}
+
+
+/* Process new data from the virtual channel */
+static void
+lspci_process(STREAM s)
+{
+	unsigned int pkglen;
+	static char *rest = NULL;
+	char *buf;
+
+	pkglen = s->end - s->p;
+	/* str_handle_lines requires null terminated strings */
+	buf = xmalloc(pkglen + 1);
+	STRNCPY(buf, (char *) s->p, pkglen + 1);
+#if 0
+	printf("lspci recv:\n");
+	hexdump(s->p, pkglen);
+#endif
+
+	str_handle_lines(buf, &rest, lspci_process_line, NULL);
+	xfree(buf);
+}
+
+/* Initialize this module: Register the lspci channel */
+RD_BOOL
+lspci_init(void)
+{
+	lspci_channel =
+		channel_register("lspci", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
+				 lspci_process);
+	return (lspci_channel != NULL);
+}
+
+/* Send data to channel */
+static void
+lspci_send(const char *output)
+{
+	STREAM s;
+	size_t len;
+
+	len = strlen(output);
+	s = channel_init(lspci_channel, len);
+	out_uint8p(s, output, len) s_mark_end(s);
+
+#if 0
+	printf("lspci send:\n");
+	hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
+#endif
+
+	channel_send(s, lspci_channel);
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/mcs.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/mcs.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/mcs.c	(revision 55121)
@@ -0,0 +1,367 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - Multipoint Communications Service
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+
+uint16 g_mcs_userid;
+extern VCHANNEL g_channels[];
+extern unsigned int g_num_channels;
+
+
+/* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
+static void
+mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
+{
+	ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 32);
+	ber_out_integer(s, max_channels);
+	ber_out_integer(s, max_users);
+	ber_out_integer(s, max_tokens);
+	ber_out_integer(s, 1);	/* num_priorities */
+	ber_out_integer(s, 0);	/* min_throughput */
+	ber_out_integer(s, 1);	/* max_height */
+	ber_out_integer(s, max_pdusize);
+	ber_out_integer(s, 2);	/* ver_protocol */
+}
+
+/* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
+static RD_BOOL
+mcs_parse_domain_params(STREAM s)
+{
+	int length;
+
+	ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
+	in_uint8s(s, length);
+
+	return s_check(s);
+}
+
+/* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
+static void
+mcs_send_connect_initial(STREAM mcs_data)
+{
+	int datalen = mcs_data->end - mcs_data->data;
+	int length = 9 + 3 * 34 + 4 + datalen;
+	STREAM s;
+
+	s = iso_init(length + 5);
+
+	ber_out_header(s, MCS_CONNECT_INITIAL, length);
+	ber_out_header(s, BER_TAG_OCTET_STRING, 1);	/* calling domain */
+	out_uint8(s, 1);
+	ber_out_header(s, BER_TAG_OCTET_STRING, 1);	/* called domain */
+	out_uint8(s, 1);
+
+	ber_out_header(s, BER_TAG_BOOLEAN, 1);
+	out_uint8(s, 0xff);	/* upward flag */
+
+	mcs_out_domain_params(s, 34, 2, 0, 0xffff);	/* target params */
+	mcs_out_domain_params(s, 1, 1, 1, 0x420);	/* min params */
+	mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff);	/* max params */
+
+	ber_out_header(s, BER_TAG_OCTET_STRING, datalen);
+	out_uint8p(s, mcs_data->data, datalen);
+
+	s_mark_end(s);
+	iso_send(s);
+}
+
+/* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
+static RD_BOOL
+mcs_recv_connect_response(STREAM mcs_data)
+{
+	uint8 result;
+	int length;
+	STREAM s;
+
+	s = iso_recv(NULL);
+	if (s == NULL)
+		return False;
+
+	ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);
+
+	ber_parse_header(s, BER_TAG_RESULT, &length);
+	in_uint8(s, result);
+	if (result != 0)
+	{
+		error("MCS connect: %d\n", result);
+		return False;
+	}
+
+	ber_parse_header(s, BER_TAG_INTEGER, &length);
+	in_uint8s(s, length);	/* connect id */
+	mcs_parse_domain_params(s);
+
+	ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
+
+	sec_process_mcs_data(s);
+	/*
+	   if (length > mcs_data->size)
+	   {
+	   error("MCS data length %d, expected %d\n", length,
+	   mcs_data->size);
+	   length = mcs_data->size;
+	   }
+
+	   in_uint8a(s, mcs_data->data, length);
+	   mcs_data->p = mcs_data->data;
+	   mcs_data->end = mcs_data->data + length;
+	 */
+	return s_check_end(s);
+}
+
+/* Send an EDrq message (ASN.1 PER) */
+static void
+mcs_send_edrq(void)
+{
+	STREAM s;
+
+	s = iso_init(5);
+
+	out_uint8(s, (MCS_EDRQ << 2));
+	out_uint16_be(s, 1);	/* height */
+	out_uint16_be(s, 1);	/* interval */
+
+	s_mark_end(s);
+	iso_send(s);
+}
+
+/* Send an AUrq message (ASN.1 PER) */
+static void
+mcs_send_aurq(void)
+{
+	STREAM s;
+
+	s = iso_init(1);
+
+	out_uint8(s, (MCS_AURQ << 2));
+
+	s_mark_end(s);
+	iso_send(s);
+}
+
+/* Expect a AUcf message (ASN.1 PER) */
+static RD_BOOL
+mcs_recv_aucf(uint16 * mcs_userid)
+{
+	uint8 opcode, result;
+	STREAM s;
+
+	s = iso_recv(NULL);
+	if (s == NULL)
+		return False;
+
+	in_uint8(s, opcode);
+	if ((opcode >> 2) != MCS_AUCF)
+	{
+		error("expected AUcf, got %d\n", opcode);
+		return False;
+	}
+
+	in_uint8(s, result);
+	if (result != 0)
+	{
+		error("AUrq: %d\n", result);
+		return False;
+	}
+
+	if (opcode & 2)
+		in_uint16_be(s, *mcs_userid);
+
+	return s_check_end(s);
+}
+
+/* Send a CJrq message (ASN.1 PER) */
+static void
+mcs_send_cjrq(uint16 chanid)
+{
+	STREAM s;
+
+	DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));
+
+	s = iso_init(5);
+
+	out_uint8(s, (MCS_CJRQ << 2));
+	out_uint16_be(s, g_mcs_userid);
+	out_uint16_be(s, chanid);
+
+	s_mark_end(s);
+	iso_send(s);
+}
+
+/* Expect a CJcf message (ASN.1 PER) */
+static RD_BOOL
+mcs_recv_cjcf(void)
+{
+	uint8 opcode, result;
+	STREAM s;
+
+	s = iso_recv(NULL);
+	if (s == NULL)
+		return False;
+
+	in_uint8(s, opcode);
+	if ((opcode >> 2) != MCS_CJCF)
+	{
+		error("expected CJcf, got %d\n", opcode);
+		return False;
+	}
+
+	in_uint8(s, result);
+	if (result != 0)
+	{
+		error("CJrq: %d\n", result);
+		return False;
+	}
+
+	in_uint8s(s, 4);	/* mcs_userid, req_chanid */
+	if (opcode & 2)
+		in_uint8s(s, 2);	/* join_chanid */
+
+	return s_check_end(s);
+}
+
+/* Initialise an MCS transport data packet */
+STREAM
+mcs_init(int length)
+{
+	STREAM s;
+
+	s = iso_init(length + 8);
+	s_push_layer(s, mcs_hdr, 8);
+
+	return s;
+}
+
+/* Send an MCS transport data packet to a specific channel */
+void
+mcs_send_to_channel(STREAM s, uint16 channel)
+{
+	uint16 length;
+
+	s_pop_layer(s, mcs_hdr);
+	length = s->end - s->p - 8;
+	length |= 0x8000;
+
+	out_uint8(s, (MCS_SDRQ << 2));
+	out_uint16_be(s, g_mcs_userid);
+	out_uint16_be(s, channel);
+	out_uint8(s, 0x70);	/* flags */
+	out_uint16_be(s, length);
+
+	iso_send(s);
+}
+
+/* Send an MCS transport data packet to the global channel */
+void
+mcs_send(STREAM s)
+{
+	mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL);
+}
+
+/* Receive an MCS transport data packet */
+STREAM
+mcs_recv(uint16 * channel, uint8 * rdpver)
+{
+	uint8 opcode, appid, length;
+	STREAM s;
+
+	s = iso_recv(rdpver);
+	if (s == NULL)
+		return NULL;
+	if (rdpver != NULL)
+		if (*rdpver != 3)
+			return s;
+	in_uint8(s, opcode);
+	appid = opcode >> 2;
+	if (appid != MCS_SDIN)
+	{
+		if (appid != MCS_DPUM)
+		{
+			error("expected data, got %d\n", opcode);
+		}
+		return NULL;
+	}
+	in_uint8s(s, 2);	/* userid */
+	in_uint16_be(s, *channel);
+	in_uint8s(s, 1);	/* flags */
+	in_uint8(s, length);
+	if (length & 0x80)
+		in_uint8s(s, 1);	/* second byte of length */
+	return s;
+}
+
+RD_BOOL
+mcs_connect_start(char *server, char *username, char *domain, char *password,
+		  RD_BOOL reconnect, uint32 * selected_protocol)
+{
+	return iso_connect(server, username, domain, password, reconnect, selected_protocol);
+}
+
+RD_BOOL
+mcs_connect_finalize(STREAM mcs_data)
+{
+	unsigned int i;
+
+	mcs_send_connect_initial(mcs_data);
+	if (!mcs_recv_connect_response(mcs_data))
+		goto error;
+
+	mcs_send_edrq();
+
+	mcs_send_aurq();
+	if (!mcs_recv_aucf(&g_mcs_userid))
+		goto error;
+
+	mcs_send_cjrq(g_mcs_userid + MCS_USERCHANNEL_BASE);
+
+	if (!mcs_recv_cjcf())
+		goto error;
+
+	mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
+	if (!mcs_recv_cjcf())
+		goto error;
+
+	for (i = 0; i < g_num_channels; i++)
+	{
+		mcs_send_cjrq(g_channels[i].mcs_id);
+		if (!mcs_recv_cjcf())
+			goto error;
+	}
+	return True;
+
+      error:
+	iso_disconnect();
+	return False;
+}
+
+/* Disconnect from the MCS layer */
+void
+mcs_disconnect(void)
+{
+	iso_disconnect();
+}
+
+/* reset the state of the mcs layer */
+void
+mcs_reset_state(void)
+{
+	g_mcs_userid = 0;
+	iso_reset_state();
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/mppc.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/mppc.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/mppc.c	(revision 55121)
@@ -0,0 +1,379 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - RDP decompression
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "rdesktop.h"
+
+/* mppc decompression                       */
+/* http://www.faqs.org/rfcs/rfc2118.html    */
+
+/* Contacts:                                */
+
+/* hifn contact mentioned in the faq is     */
+/* Robert Friend rfriend at hifn dot com    */
+
+/* if you have questions regarding MPPC     */
+/* our contact is                           */
+/* Guus Dhaeze  GDhaeze at hifn dot com     */
+
+/* Licensing:                               */
+
+/* decompression is alright as long as we   */
+/* don't compress data                      */
+
+/* Algorithm: */
+
+/* as the rfc states the algorithm seems to */
+/* be LZ77 with a sliding buffer            */
+/* that is empty at init.                   */
+
+/* the algorithm is called LZS and is       */
+/* patented for another couple of years.    */
+
+/* more information is available in         */
+/* http://www.ietf.org/ietf/IPR/hifn-ipr-draft-friend-tls-lzs-compression.txt */
+
+
+RDPCOMP g_mppc_dict;
+
+int
+mppc_expand(uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen)
+{
+	int k, walker_len = 0, walker;
+	uint32 i = 0;
+	int next_offset, match_off;
+	int match_len;
+	int old_offset, match_bits;
+	RD_BOOL big = ctype & RDP_MPPC_BIG ? True : False;
+
+	uint8 *dict = g_mppc_dict.hist;
+
+	if ((ctype & RDP_MPPC_COMPRESSED) == 0)
+	{
+		*roff = 0;
+		*rlen = clen;
+		return 0;
+	}
+
+	if ((ctype & RDP_MPPC_RESET) != 0)
+	{
+		g_mppc_dict.roff = 0;
+	}
+
+	if ((ctype & RDP_MPPC_FLUSH) != 0)
+	{
+		memset(dict, 0, RDP_MPPC_DICT_SIZE);
+		g_mppc_dict.roff = 0;
+	}
+
+	*roff = 0;
+	*rlen = 0;
+
+	walker = g_mppc_dict.roff;
+
+	next_offset = walker;
+	old_offset = next_offset;
+	*roff = old_offset;
+	if (clen == 0)
+		return 0;
+	clen += i;
+
+	do
+	{
+		if (walker_len == 0)
+		{
+			if (i >= clen)
+				break;
+			walker = data[i++] << 24;
+			walker_len = 8;
+		}
+		if (walker >= 0)
+		{
+			if (walker_len < 8)
+			{
+				if (i >= clen)
+				{
+					if (walker != 0)
+						return -1;
+					break;
+				}
+				walker |= (data[i++] & 0xff) << (24 - walker_len);
+				walker_len += 8;
+			}
+			if (next_offset >= RDP_MPPC_DICT_SIZE)
+				return -1;
+			dict[next_offset++] = (((uint32) walker) >> ((uint32) 24));
+			walker <<= 8;
+			walker_len -= 8;
+			continue;
+		}
+		walker <<= 1;
+		/* fetch next 8-bits */
+		if (--walker_len == 0)
+		{
+			if (i >= clen)
+				return -1;
+			walker = data[i++] << 24;
+			walker_len = 8;
+		}
+		/* literal decoding */
+		if (walker >= 0)
+		{
+			if (walker_len < 8)
+			{
+				if (i >= clen)
+					return -1;
+				walker |= (data[i++] & 0xff) << (24 - walker_len);
+				walker_len += 8;
+			}
+			if (next_offset >= RDP_MPPC_DICT_SIZE)
+				return -1;
+			dict[next_offset++] = (uint8) (walker >> 24 | 0x80);
+			walker <<= 8;
+			walker_len -= 8;
+			continue;
+		}
+
+		/* decode offset  */
+		/* length pair    */
+		walker <<= 1;
+		if (--walker_len < (big ? 3 : 2))
+		{
+			if (i >= clen)
+				return -1;
+			walker |= (data[i++] & 0xff) << (24 - walker_len);
+			walker_len += 8;
+		}
+
+		if (big)
+		{
+			/* offset decoding where offset len is:
+			   -63: 11111 followed by the lower 6 bits of the value
+			   64-319: 11110 followed by the lower 8 bits of the value ( value - 64 )
+			   320-2367: 1110 followed by lower 11 bits of the value ( value - 320 )
+			   2368-65535: 110 followed by lower 16 bits of the value ( value - 2368 )
+			 */
+			switch (((uint32) walker) >> ((uint32) 29))
+			{
+				case 7:	/* - 63 */
+					for (; walker_len < 9; walker_len += 8)
+					{
+						if (i >= clen)
+							return -1;
+						walker |= (data[i++] & 0xff) << (24 - walker_len);
+					}
+					walker <<= 3;
+					match_off = ((uint32) walker) >> ((uint32) 26);
+					walker <<= 6;
+					walker_len -= 9;
+					break;
+
+				case 6:	/* 64 - 319 */
+					for (; walker_len < 11; walker_len += 8)
+					{
+						if (i >= clen)
+							return -1;
+						walker |= (data[i++] & 0xff) << (24 - walker_len);
+					}
+
+					walker <<= 3;
+					match_off = (((uint32) walker) >> ((uint32) 24)) + 64;
+					walker <<= 8;
+					walker_len -= 11;
+					break;
+
+				case 5:
+				case 4:	/* 320 - 2367 */
+					for (; walker_len < 13; walker_len += 8)
+					{
+						if (i >= clen)
+							return -1;
+						walker |= (data[i++] & 0xff) << (24 - walker_len);
+					}
+
+					walker <<= 2;
+					match_off = (((uint32) walker) >> ((uint32) 21)) + 320;
+					walker <<= 11;
+					walker_len -= 13;
+					break;
+
+				default:	/* 2368 - 65535 */
+					for (; walker_len < 17; walker_len += 8)
+					{
+						if (i >= clen)
+							return -1;
+						walker |= (data[i++] & 0xff) << (24 - walker_len);
+					}
+
+					walker <<= 1;
+					match_off = (((uint32) walker) >> ((uint32) 16)) + 2368;
+					walker <<= 16;
+					walker_len -= 17;
+					break;
+			}
+		}
+		else
+		{
+			/* offset decoding where offset len is:
+			   -63: 1111 followed by the lower 6 bits of the value
+			   64-319: 1110 followed by the lower 8 bits of the value ( value - 64 )
+			   320-8191: 110 followed by the lower 13 bits of the value ( value - 320 )
+			 */
+			switch (((uint32) walker) >> ((uint32) 30))
+			{
+				case 3:	/* - 63 */
+					if (walker_len < 8)
+					{
+						if (i >= clen)
+							return -1;
+						walker |= (data[i++] & 0xff) << (24 - walker_len);
+						walker_len += 8;
+					}
+					walker <<= 2;
+					match_off = ((uint32) walker) >> ((uint32) 26);
+					walker <<= 6;
+					walker_len -= 8;
+					break;
+
+				case 2:	/* 64 - 319 */
+					for (; walker_len < 10; walker_len += 8)
+					{
+						if (i >= clen)
+							return -1;
+						walker |= (data[i++] & 0xff) << (24 - walker_len);
+					}
+
+					walker <<= 2;
+					match_off = (((uint32) walker) >> ((uint32) 24)) + 64;
+					walker <<= 8;
+					walker_len -= 10;
+					break;
+
+				default:	/* 320 - 8191 */
+					for (; walker_len < 14; walker_len += 8)
+					{
+						if (i >= clen)
+							return -1;
+						walker |= (data[i++] & 0xff) << (24 - walker_len);
+					}
+
+					match_off = (walker >> 18) + 320;
+					walker <<= 14;
+					walker_len -= 14;
+					break;
+			}
+		}
+		if (walker_len == 0)
+		{
+			if (i >= clen)
+				return -1;
+			walker = data[i++] << 24;
+			walker_len = 8;
+		}
+
+		/* decode length of match */
+		match_len = 0;
+		if (walker >= 0)
+		{		/* special case - length of 3 is in bit 0 */
+			match_len = 3;
+			walker <<= 1;
+			walker_len--;
+		}
+		else
+		{
+			/* this is how it works len of:
+			   4-7: 10 followed by 2 bits of the value
+			   8-15: 110 followed by 3 bits of the value
+			   16-31: 1110 followed by 4 bits of the value
+			   32-63: .... and so forth
+			   64-127:
+			   128-255:
+			   256-511:
+			   512-1023:
+			   1024-2047:
+			   2048-4095:
+			   4096-8191:
+
+			   i.e. 4097 is encoded as: 111111111110 000000000001
+			   meaning 4096 + 1...
+			 */
+			match_bits = big ? 14 : 11;	/* 11 or 14 bits of value at most */
+			do
+			{
+				walker <<= 1;
+				if (--walker_len == 0)
+				{
+					if (i >= clen)
+						return -1;
+					walker = data[i++] << 24;
+					walker_len = 8;
+				}
+				if (walker >= 0)
+					break;
+				if (--match_bits == 0)
+				{
+					return -1;
+				}
+			}
+			while (1);
+			match_len = (big ? 16 : 13) - match_bits;
+			walker <<= 1;
+			if (--walker_len < match_len)
+			{
+				for (; walker_len < match_len; walker_len += 8)
+				{
+					if (i >= clen)
+					{
+						return -1;
+					}
+					walker |= (data[i++] & 0xff) << (24 - walker_len);
+				}
+			}
+
+			match_bits = match_len;
+			match_len =
+				((walker >> (32 - match_bits)) & (~(-1 << match_bits))) | (1 <<
+											   match_bits);
+			walker <<= match_bits;
+			walker_len -= match_bits;
+		}
+		if (next_offset + match_len >= RDP_MPPC_DICT_SIZE)
+		{
+			return -1;
+		}
+		/* memory areas can overlap - meaning we can't use memXXX functions */
+		k = (next_offset - match_off) & (big ? 65535 : 8191);
+		do
+		{
+			dict[next_offset++] = dict[k++];
+		}
+		while (--match_len != 0);
+	}
+	while (1);
+
+	/* store history offset */
+	g_mppc_dict.roff = next_offset;
+
+	*roff = old_offset;
+	*rlen = next_offset - old_offset;
+
+	return 0;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/orders.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/orders.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/orders.c	(revision 55121)
@@ -0,0 +1,1456 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   RDP order processing
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+#include "orders.h"
+
+extern uint8 *g_next_packet;
+static RDP_ORDER_STATE g_order_state;
+extern RDP_VERSION g_rdp_version;
+
+/* Read field indicating which parameters are present */
+static void
+rdp_in_present(STREAM s, uint32 * present, uint8 flags, int size)
+{
+	uint8 bits;
+	int i;
+
+	if (flags & RDP_ORDER_SMALL)
+	{
+		size--;
+	}
+
+	if (flags & RDP_ORDER_TINY)
+	{
+		if (size < 2)
+			size = 0;
+		else
+			size -= 2;
+	}
+
+	*present = 0;
+	for (i = 0; i < size; i++)
+	{
+		in_uint8(s, bits);
+		*present |= bits << (i * 8);
+	}
+}
+
+/* Read a co-ordinate (16-bit, or 8-bit delta) */
+static void
+rdp_in_coord(STREAM s, sint16 * coord, RD_BOOL delta)
+{
+	sint8 change;
+
+	if (delta)
+	{
+		in_uint8(s, change);
+		*coord += change;
+	}
+	else
+	{
+		in_uint16_le(s, *coord);
+	}
+}
+
+/* Parse a delta co-ordinate in polyline/polygon order form */
+static int
+parse_delta(uint8 * buffer, int *offset)
+{
+	int value = buffer[(*offset)++];
+	int two_byte = value & 0x80;
+
+	if (value & 0x40)	/* sign bit */
+		value |= ~0x3f;
+	else
+		value &= 0x3f;
+
+	if (two_byte)
+		value = (value << 8) | buffer[(*offset)++];
+
+	return value;
+}
+
+/* Read a colour entry */
+static void
+rdp_in_colour(STREAM s, uint32 * colour)
+{
+	uint32 i;
+	in_uint8(s, i);
+	*colour = i;
+	in_uint8(s, i);
+	*colour |= i << 8;
+	in_uint8(s, i);
+	*colour |= i << 16;
+}
+
+/* Parse bounds information */
+static RD_BOOL
+rdp_parse_bounds(STREAM s, BOUNDS * bounds)
+{
+	uint8 present;
+
+	in_uint8(s, present);
+
+	if (present & 1)
+		rdp_in_coord(s, &bounds->left, False);
+	else if (present & 16)
+		rdp_in_coord(s, &bounds->left, True);
+
+	if (present & 2)
+		rdp_in_coord(s, &bounds->top, False);
+	else if (present & 32)
+		rdp_in_coord(s, &bounds->top, True);
+
+	if (present & 4)
+		rdp_in_coord(s, &bounds->right, False);
+	else if (present & 64)
+		rdp_in_coord(s, &bounds->right, True);
+
+	if (present & 8)
+		rdp_in_coord(s, &bounds->bottom, False);
+	else if (present & 128)
+		rdp_in_coord(s, &bounds->bottom, True);
+
+	return s_check(s);
+}
+
+/* Parse a pen */
+static RD_BOOL
+rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
+{
+	if (present & 1)
+		in_uint8(s, pen->style);
+
+	if (present & 2)
+		in_uint8(s, pen->width);
+
+	if (present & 4)
+		rdp_in_colour(s, &pen->colour);
+
+	return s_check(s);
+}
+
+static void
+setup_brush(BRUSH * out_brush, BRUSH * in_brush)
+{
+	BRUSHDATA *brush_data;
+	uint8 cache_idx;
+	uint8 colour_code;
+
+	memcpy(out_brush, in_brush, sizeof(BRUSH));
+	if (out_brush->style & 0x80)
+	{
+		colour_code = out_brush->style & 0x0f;
+		cache_idx = out_brush->pattern[0];
+		brush_data = cache_get_brush_data(colour_code, cache_idx);
+		if ((brush_data == NULL) || (brush_data->data == NULL))
+		{
+			error("error getting brush data, style %x\n", out_brush->style);
+			out_brush->bd = NULL;
+			memset(out_brush->pattern, 0, 8);
+		}
+		else
+		{
+			out_brush->bd = brush_data;
+		}
+		out_brush->style = 3;
+	}
+}
+
+/* Parse a brush */
+static RD_BOOL
+rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
+{
+	if (present & 1)
+		in_uint8(s, brush->xorigin);
+
+	if (present & 2)
+		in_uint8(s, brush->yorigin);
+
+	if (present & 4)
+		in_uint8(s, brush->style);
+
+	if (present & 8)
+		in_uint8(s, brush->pattern[0]);
+
+	if (present & 16)
+		in_uint8a(s, &brush->pattern[1], 7);
+
+	return s_check(s);
+}
+
+/* Process a destination blt order */
+static void
+process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	if (present & 0x01)
+		rdp_in_coord(s, &os->x, delta);
+
+	if (present & 0x02)
+		rdp_in_coord(s, &os->y, delta);
+
+	if (present & 0x04)
+		rdp_in_coord(s, &os->cx, delta);
+
+	if (present & 0x08)
+		rdp_in_coord(s, &os->cy, delta);
+
+	if (present & 0x10)
+		in_uint8(s, os->opcode);
+
+	DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
+	       os->opcode, os->x, os->y, os->cx, os->cy));
+
+	ui_destblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy);
+}
+
+/* Process a pattern blt order */
+static void
+process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	BRUSH brush;
+
+	if (present & 0x0001)
+		rdp_in_coord(s, &os->x, delta);
+
+	if (present & 0x0002)
+		rdp_in_coord(s, &os->y, delta);
+
+	if (present & 0x0004)
+		rdp_in_coord(s, &os->cx, delta);
+
+	if (present & 0x0008)
+		rdp_in_coord(s, &os->cy, delta);
+
+	if (present & 0x0010)
+		in_uint8(s, os->opcode);
+
+	if (present & 0x0020)
+		rdp_in_colour(s, &os->bgcolour);
+
+	if (present & 0x0040)
+		rdp_in_colour(s, &os->fgcolour);
+
+	rdp_parse_brush(s, &os->brush, present >> 7);
+
+	DEBUG(("PATBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,bs=%d,bg=0x%x,fg=0x%x)\n", os->opcode, os->x,
+	       os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour));
+
+	setup_brush(&brush, &os->brush);
+
+	ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy,
+		  &brush, os->bgcolour, os->fgcolour);
+}
+
+/* Process a screen blt order */
+static void
+process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	if (present & 0x0001)
+		rdp_in_coord(s, &os->x, delta);
+
+	if (present & 0x0002)
+		rdp_in_coord(s, &os->y, delta);
+
+	if (present & 0x0004)
+		rdp_in_coord(s, &os->cx, delta);
+
+	if (present & 0x0008)
+		rdp_in_coord(s, &os->cy, delta);
+
+	if (present & 0x0010)
+		in_uint8(s, os->opcode);
+
+	if (present & 0x0020)
+		rdp_in_coord(s, &os->srcx, delta);
+
+	if (present & 0x0040)
+		rdp_in_coord(s, &os->srcy, delta);
+
+	DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
+	       os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy));
+
+	ui_screenblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, os->srcx, os->srcy);
+}
+
+/* Process a line order */
+static void
+process_line(STREAM s, LINE_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	if (present & 0x0001)
+		in_uint16_le(s, os->mixmode);
+
+	if (present & 0x0002)
+		rdp_in_coord(s, &os->startx, delta);
+
+	if (present & 0x0004)
+		rdp_in_coord(s, &os->starty, delta);
+
+	if (present & 0x0008)
+		rdp_in_coord(s, &os->endx, delta);
+
+	if (present & 0x0010)
+		rdp_in_coord(s, &os->endy, delta);
+
+	if (present & 0x0020)
+		rdp_in_colour(s, &os->bgcolour);
+
+	if (present & 0x0040)
+		in_uint8(s, os->opcode);
+
+	rdp_parse_pen(s, &os->pen, present >> 7);
+
+	DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dy=%d,fg=0x%x)\n",
+	       os->opcode, os->startx, os->starty, os->endx, os->endy, os->pen.colour));
+
+	if (os->opcode < 0x01 || os->opcode > 0x10)
+	{
+		error("bad ROP2 0x%x\n", os->opcode);
+		return;
+	}
+
+	ui_line(os->opcode - 1, os->startx, os->starty, os->endx, os->endy, &os->pen);
+}
+
+/* Process an opaque rectangle order */
+static void
+process_rect(STREAM s, RECT_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	uint32 i;
+	if (present & 0x01)
+		rdp_in_coord(s, &os->x, delta);
+
+	if (present & 0x02)
+		rdp_in_coord(s, &os->y, delta);
+
+	if (present & 0x04)
+		rdp_in_coord(s, &os->cx, delta);
+
+	if (present & 0x08)
+		rdp_in_coord(s, &os->cy, delta);
+
+	if (present & 0x10)
+	{
+		in_uint8(s, i);
+		os->colour = (os->colour & 0xffffff00) | i;
+	}
+
+	if (present & 0x20)
+	{
+		in_uint8(s, i);
+		os->colour = (os->colour & 0xffff00ff) | (i << 8);
+	}
+
+	if (present & 0x40)
+	{
+		in_uint8(s, i);
+		os->colour = (os->colour & 0xff00ffff) | (i << 16);
+	}
+
+	DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os->x, os->y, os->cx, os->cy, os->colour));
+
+	ui_rect(os->x, os->y, os->cx, os->cy, os->colour);
+}
+
+/* Process a desktop save order */
+static void
+process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	int width, height;
+
+	if (present & 0x01)
+		in_uint32_le(s, os->offset);
+
+	if (present & 0x02)
+		rdp_in_coord(s, &os->left, delta);
+
+	if (present & 0x04)
+		rdp_in_coord(s, &os->top, delta);
+
+	if (present & 0x08)
+		rdp_in_coord(s, &os->right, delta);
+
+	if (present & 0x10)
+		rdp_in_coord(s, &os->bottom, delta);
+
+	if (present & 0x20)
+		in_uint8(s, os->action);
+
+	DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
+	       os->left, os->top, os->right, os->bottom, os->offset, os->action));
+
+	width = os->right - os->left + 1;
+	height = os->bottom - os->top + 1;
+
+	if (os->action == 0)
+		ui_desktop_save(os->offset, os->left, os->top, width, height);
+	else
+		ui_desktop_restore(os->offset, os->left, os->top, width, height);
+}
+
+/* Process a memory blt order */
+static void
+process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	RD_HBITMAP bitmap;
+
+	if (present & 0x0001)
+	{
+		in_uint8(s, os->cache_id);
+		in_uint8(s, os->colour_table);
+	}
+
+	if (present & 0x0002)
+		rdp_in_coord(s, &os->x, delta);
+
+	if (present & 0x0004)
+		rdp_in_coord(s, &os->y, delta);
+
+	if (present & 0x0008)
+		rdp_in_coord(s, &os->cx, delta);
+
+	if (present & 0x0010)
+		rdp_in_coord(s, &os->cy, delta);
+
+	if (present & 0x0020)
+		in_uint8(s, os->opcode);
+
+	if (present & 0x0040)
+		rdp_in_coord(s, &os->srcx, delta);
+
+	if (present & 0x0080)
+		rdp_in_coord(s, &os->srcy, delta);
+
+	if (present & 0x0100)
+		in_uint16_le(s, os->cache_idx);
+
+	DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
+	       os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx));
+
+	bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
+	if (bitmap == NULL)
+		return;
+
+	ui_memblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, bitmap, os->srcx, os->srcy);
+}
+
+/* Process a 3-way blt order */
+static void
+process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	RD_HBITMAP bitmap;
+	BRUSH brush;
+
+	if (present & 0x000001)
+	{
+		in_uint8(s, os->cache_id);
+		in_uint8(s, os->colour_table);
+	}
+
+	if (present & 0x000002)
+		rdp_in_coord(s, &os->x, delta);
+
+	if (present & 0x000004)
+		rdp_in_coord(s, &os->y, delta);
+
+	if (present & 0x000008)
+		rdp_in_coord(s, &os->cx, delta);
+
+	if (present & 0x000010)
+		rdp_in_coord(s, &os->cy, delta);
+
+	if (present & 0x000020)
+		in_uint8(s, os->opcode);
+
+	if (present & 0x000040)
+		rdp_in_coord(s, &os->srcx, delta);
+
+	if (present & 0x000080)
+		rdp_in_coord(s, &os->srcy, delta);
+
+	if (present & 0x000100)
+		rdp_in_colour(s, &os->bgcolour);
+
+	if (present & 0x000200)
+		rdp_in_colour(s, &os->fgcolour);
+
+	rdp_parse_brush(s, &os->brush, present >> 10);
+
+	if (present & 0x008000)
+		in_uint16_le(s, os->cache_idx);
+
+	if (present & 0x010000)
+		in_uint16_le(s, os->unknown);
+
+	DEBUG(("TRIBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
+	       os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx,
+	       os->brush.style, os->bgcolour, os->fgcolour));
+
+	bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
+	if (bitmap == NULL)
+		return;
+
+	setup_brush(&brush, &os->brush);
+
+	ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy,
+		  bitmap, os->srcx, os->srcy, &brush, os->bgcolour, os->fgcolour);
+}
+
+/* Process a polygon order */
+static void
+process_polygon(STREAM s, POLYGON_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	int index, data, next;
+	uint8 flags = 0;
+	RD_POINT *points;
+
+	if (present & 0x01)
+		rdp_in_coord(s, &os->x, delta);
+
+	if (present & 0x02)
+		rdp_in_coord(s, &os->y, delta);
+
+	if (present & 0x04)
+		in_uint8(s, os->opcode);
+
+	if (present & 0x08)
+		in_uint8(s, os->fillmode);
+
+	if (present & 0x10)
+		rdp_in_colour(s, &os->fgcolour);
+
+	if (present & 0x20)
+		in_uint8(s, os->npoints);
+
+	if (present & 0x40)
+	{
+		in_uint8(s, os->datasize);
+		in_uint8a(s, os->data, os->datasize);
+	}
+
+	DEBUG(("POLYGON(x=%d,y=%d,op=0x%x,fm=%d,fg=0x%x,n=%d,sz=%d)\n",
+	       os->x, os->y, os->opcode, os->fillmode, os->fgcolour, os->npoints, os->datasize));
+
+	DEBUG(("Data: "));
+
+	for (index = 0; index < os->datasize; index++)
+		DEBUG(("%02x ", os->data[index]));
+
+	DEBUG(("\n"));
+
+	if (os->opcode < 0x01 || os->opcode > 0x10)
+	{
+		error("bad ROP2 0x%x\n", os->opcode);
+		return;
+	}
+
+	points = (RD_POINT *) xmalloc((os->npoints + 1) * sizeof(RD_POINT));
+	memset(points, 0, (os->npoints + 1) * sizeof(RD_POINT));
+
+	points[0].x = os->x;
+	points[0].y = os->y;
+
+	index = 0;
+	data = ((os->npoints - 1) / 4) + 1;
+	for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++)
+	{
+		if ((next - 1) % 4 == 0)
+			flags = os->data[index++];
+
+		if (~flags & 0x80)
+			points[next].x = parse_delta(os->data, &data);
+
+		if (~flags & 0x40)
+			points[next].y = parse_delta(os->data, &data);
+
+		flags <<= 2;
+	}
+
+	if (next - 1 == os->npoints)
+		ui_polygon(os->opcode - 1, os->fillmode, points, os->npoints + 1, NULL, 0,
+			   os->fgcolour);
+	else
+		error("polygon parse error\n");
+
+	xfree(points);
+}
+
+/* Process a polygon2 order */
+static void
+process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	int index, data, next;
+	uint8 flags = 0;
+	RD_POINT *points;
+	BRUSH brush;
+
+	if (present & 0x0001)
+		rdp_in_coord(s, &os->x, delta);
+
+	if (present & 0x0002)
+		rdp_in_coord(s, &os->y, delta);
+
+	if (present & 0x0004)
+		in_uint8(s, os->opcode);
+
+	if (present & 0x0008)
+		in_uint8(s, os->fillmode);
+
+	if (present & 0x0010)
+		rdp_in_colour(s, &os->bgcolour);
+
+	if (present & 0x0020)
+		rdp_in_colour(s, &os->fgcolour);
+
+	rdp_parse_brush(s, &os->brush, present >> 6);
+
+	if (present & 0x0800)
+		in_uint8(s, os->npoints);
+
+	if (present & 0x1000)
+	{
+		in_uint8(s, os->datasize);
+		in_uint8a(s, os->data, os->datasize);
+	}
+
+	DEBUG(("POLYGON2(x=%d,y=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x,n=%d,sz=%d)\n",
+	       os->x, os->y, os->opcode, os->fillmode, os->brush.style, os->bgcolour, os->fgcolour,
+	       os->npoints, os->datasize));
+
+	DEBUG(("Data: "));
+
+	for (index = 0; index < os->datasize; index++)
+		DEBUG(("%02x ", os->data[index]));
+
+	DEBUG(("\n"));
+
+	if (os->opcode < 0x01 || os->opcode > 0x10)
+	{
+		error("bad ROP2 0x%x\n", os->opcode);
+		return;
+	}
+
+	setup_brush(&brush, &os->brush);
+
+	points = (RD_POINT *) xmalloc((os->npoints + 1) * sizeof(RD_POINT));
+	memset(points, 0, (os->npoints + 1) * sizeof(RD_POINT));
+
+	points[0].x = os->x;
+	points[0].y = os->y;
+
+	index = 0;
+	data = ((os->npoints - 1) / 4) + 1;
+	for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++)
+	{
+		if ((next - 1) % 4 == 0)
+			flags = os->data[index++];
+
+		if (~flags & 0x80)
+			points[next].x = parse_delta(os->data, &data);
+
+		if (~flags & 0x40)
+			points[next].y = parse_delta(os->data, &data);
+
+		flags <<= 2;
+	}
+
+	if (next - 1 == os->npoints)
+		ui_polygon(os->opcode - 1, os->fillmode, points, os->npoints + 1,
+			   &brush, os->bgcolour, os->fgcolour);
+	else
+		error("polygon2 parse error\n");
+
+	xfree(points);
+}
+
+/* Process a polyline order */
+static void
+process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	int index, next, data;
+	uint8 flags = 0;
+	PEN pen;
+	RD_POINT *points;
+
+	if (present & 0x01)
+		rdp_in_coord(s, &os->x, delta);
+
+	if (present & 0x02)
+		rdp_in_coord(s, &os->y, delta);
+
+	if (present & 0x04)
+		in_uint8(s, os->opcode);
+
+	if (present & 0x10)
+		rdp_in_colour(s, &os->fgcolour);
+
+	if (present & 0x20)
+		in_uint8(s, os->lines);
+
+	if (present & 0x40)
+	{
+		in_uint8(s, os->datasize);
+		in_uint8a(s, os->data, os->datasize);
+	}
+
+	DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
+	       os->x, os->y, os->opcode, os->fgcolour, os->lines, os->datasize));
+
+	DEBUG(("Data: "));
+
+	for (index = 0; index < os->datasize; index++)
+		DEBUG(("%02x ", os->data[index]));
+
+	DEBUG(("\n"));
+
+	if (os->opcode < 0x01 || os->opcode > 0x10)
+	{
+		error("bad ROP2 0x%x\n", os->opcode);
+		return;
+	}
+
+	points = (RD_POINT *) xmalloc((os->lines + 1) * sizeof(RD_POINT));
+	memset(points, 0, (os->lines + 1) * sizeof(RD_POINT));
+
+	points[0].x = os->x;
+	points[0].y = os->y;
+	pen.style = pen.width = 0;
+	pen.colour = os->fgcolour;
+
+	index = 0;
+	data = ((os->lines - 1) / 4) + 1;
+	for (next = 1; (next <= os->lines) && (data < os->datasize); next++)
+	{
+		if ((next - 1) % 4 == 0)
+			flags = os->data[index++];
+
+		if (~flags & 0x80)
+			points[next].x = parse_delta(os->data, &data);
+
+		if (~flags & 0x40)
+			points[next].y = parse_delta(os->data, &data);
+
+		flags <<= 2;
+	}
+
+	if (next - 1 == os->lines)
+		ui_polyline(os->opcode - 1, points, os->lines + 1, &pen);
+	else
+		error("polyline parse error\n");
+
+	xfree(points);
+}
+
+/* Process an ellipse order */
+static void
+process_ellipse(STREAM s, ELLIPSE_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	if (present & 0x01)
+		rdp_in_coord(s, &os->left, delta);
+
+	if (present & 0x02)
+		rdp_in_coord(s, &os->top, delta);
+
+	if (present & 0x04)
+		rdp_in_coord(s, &os->right, delta);
+
+	if (present & 0x08)
+		rdp_in_coord(s, &os->bottom, delta);
+
+	if (present & 0x10)
+		in_uint8(s, os->opcode);
+
+	if (present & 0x20)
+		in_uint8(s, os->fillmode);
+
+	if (present & 0x40)
+		rdp_in_colour(s, &os->fgcolour);
+
+	DEBUG(("ELLIPSE(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,fg=0x%x)\n", os->left, os->top,
+	       os->right, os->bottom, os->opcode, os->fillmode, os->fgcolour));
+
+	ui_ellipse(os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left,
+		   os->bottom - os->top, NULL, 0, os->fgcolour);
+}
+
+/* Process an ellipse2 order */
+static void
+process_ellipse2(STREAM s, ELLIPSE2_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	BRUSH brush;
+
+	if (present & 0x0001)
+		rdp_in_coord(s, &os->left, delta);
+
+	if (present & 0x0002)
+		rdp_in_coord(s, &os->top, delta);
+
+	if (present & 0x0004)
+		rdp_in_coord(s, &os->right, delta);
+
+	if (present & 0x0008)
+		rdp_in_coord(s, &os->bottom, delta);
+
+	if (present & 0x0010)
+		in_uint8(s, os->opcode);
+
+	if (present & 0x0020)
+		in_uint8(s, os->fillmode);
+
+	if (present & 0x0040)
+		rdp_in_colour(s, &os->bgcolour);
+
+	if (present & 0x0080)
+		rdp_in_colour(s, &os->fgcolour);
+
+	rdp_parse_brush(s, &os->brush, present >> 8);
+
+	DEBUG(("ELLIPSE2(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
+	       os->left, os->top, os->right, os->bottom, os->opcode, os->fillmode, os->brush.style,
+	       os->bgcolour, os->fgcolour));
+
+	setup_brush(&brush, &os->brush);
+
+	ui_ellipse(os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left,
+		   os->bottom - os->top, &brush, os->bgcolour, os->fgcolour);
+}
+
+/* Process a text order */
+static void
+process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, RD_BOOL delta)
+{
+	int i;
+	BRUSH brush;
+
+	if (present & 0x000001)
+		in_uint8(s, os->font);
+
+	if (present & 0x000002)
+		in_uint8(s, os->flags);
+
+	if (present & 0x000004)
+		in_uint8(s, os->opcode);
+
+	if (present & 0x000008)
+		in_uint8(s, os->mixmode);
+
+	if (present & 0x000010)
+		rdp_in_colour(s, &os->fgcolour);
+
+	if (present & 0x000020)
+		rdp_in_colour(s, &os->bgcolour);
+
+	if (present & 0x000040)
+		in_uint16_le(s, os->clipleft);
+
+	if (present & 0x000080)
+		in_uint16_le(s, os->cliptop);
+
+	if (present & 0x000100)
+		in_uint16_le(s, os->clipright);
+
+	if (present & 0x000200)
+		in_uint16_le(s, os->clipbottom);
+
+	if (present & 0x000400)
+		in_uint16_le(s, os->boxleft);
+
+	if (present & 0x000800)
+		in_uint16_le(s, os->boxtop);
+
+	if (present & 0x001000)
+		in_uint16_le(s, os->boxright);
+
+	if (present & 0x002000)
+		in_uint16_le(s, os->boxbottom);
+
+	rdp_parse_brush(s, &os->brush, present >> 14);
+
+	if (present & 0x080000)
+		in_uint16_le(s, os->x);
+
+	if (present & 0x100000)
+		in_uint16_le(s, os->y);
+
+	if (present & 0x200000)
+	{
+		in_uint8(s, os->length);
+		in_uint8a(s, os->text, os->length);
+	}
+
+	DEBUG(("TEXT2(x=%d,y=%d,cl=%d,ct=%d,cr=%d,cb=%d,bl=%d,bt=%d,br=%d,bb=%d,bs=%d,bg=0x%x,fg=0x%x,font=%d,fl=0x%x,op=0x%x,mix=%d,n=%d)\n", os->x, os->y, os->clipleft, os->cliptop, os->clipright, os->clipbottom, os->boxleft, os->boxtop, os->boxright, os->boxbottom, os->brush.style, os->bgcolour, os->fgcolour, os->font, os->flags, os->opcode, os->mixmode, os->length));
+
+	DEBUG(("Text: "));
+
+	for (i = 0; i < os->length; i++)
+		DEBUG(("%02x ", os->text[i]));
+
+	DEBUG(("\n"));
+
+	setup_brush(&brush, &os->brush);
+
+	ui_draw_text(os->font, os->flags, os->opcode - 1, os->mixmode, os->x, os->y,
+		     os->clipleft, os->cliptop, os->clipright - os->clipleft,
+		     os->clipbottom - os->cliptop, os->boxleft, os->boxtop,
+		     os->boxright - os->boxleft, os->boxbottom - os->boxtop,
+		     &brush, os->bgcolour, os->fgcolour, os->text, os->length);
+}
+
+/* Process a raw bitmap cache order */
+static void
+process_raw_bmpcache(STREAM s)
+{
+	RD_HBITMAP bitmap;
+	uint16 cache_idx, bufsize;
+	uint8 cache_id, width, height, bpp, Bpp;
+	uint8 *data, *inverted;
+	int y;
+
+	in_uint8(s, cache_id);
+	in_uint8s(s, 1);	/* pad */
+	in_uint8(s, width);
+	in_uint8(s, height);
+	in_uint8(s, bpp);
+	Bpp = (bpp + 7) / 8;
+	in_uint16_le(s, bufsize);
+	in_uint16_le(s, cache_idx);
+	in_uint8p(s, data, bufsize);
+
+	DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
+	inverted = (uint8 *) xmalloc(width * height * Bpp);
+	for (y = 0; y < height; y++)
+	{
+		memcpy(&inverted[(height - y - 1) * (width * Bpp)], &data[y * (width * Bpp)],
+		       width * Bpp);
+	}
+
+	bitmap = ui_create_bitmap(width, height, inverted);
+	xfree(inverted);
+	cache_put_bitmap(cache_id, cache_idx, bitmap);
+}
+
+/* Process a bitmap cache order */
+static void
+process_bmpcache(STREAM s)
+{
+	RD_HBITMAP bitmap;
+	uint16 cache_idx, size;
+	uint8 cache_id, width, height, bpp, Bpp;
+	uint8 *data, *bmpdata;
+	uint16 bufsize, pad2, row_size, final_size;
+	uint8 pad1;
+
+	pad2 = row_size = final_size = 0xffff;	/* Shut the compiler up */
+
+	in_uint8(s, cache_id);
+	in_uint8(s, pad1);	/* pad */
+	in_uint8(s, width);
+	in_uint8(s, height);
+	in_uint8(s, bpp);
+	Bpp = (bpp + 7) / 8;
+	in_uint16_le(s, bufsize);	/* bufsize */
+	in_uint16_le(s, cache_idx);
+
+	if (g_rdp_version >= RDP_V5)
+	{
+		size = bufsize;
+	}
+	else
+	{
+
+		/* Begin compressedBitmapData */
+		in_uint16_le(s, pad2);	/* pad */
+		in_uint16_le(s, size);
+		/*      in_uint8s(s, 4);  *//* row_size, final_size */
+		in_uint16_le(s, row_size);
+		in_uint16_le(s, final_size);
+
+	}
+	in_uint8p(s, data, size);
+
+	DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d,bpp=%d,size=%d,pad1=%d,bufsize=%d,pad2=%d,rs=%d,fs=%d)\n", width, height, cache_id, cache_idx, bpp, size, pad1, bufsize, pad2, row_size, final_size));
+
+	bmpdata = (uint8 *) xmalloc(width * height * Bpp);
+
+	if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
+	{
+		bitmap = ui_create_bitmap(width, height, bmpdata);
+		cache_put_bitmap(cache_id, cache_idx, bitmap);
+	}
+	else
+	{
+		DEBUG(("Failed to decompress bitmap data\n"));
+	}
+
+	xfree(bmpdata);
+}
+
+/* Process a bitmap cache v2 order */
+static void
+process_bmpcache2(STREAM s, uint16 flags, RD_BOOL compressed)
+{
+	RD_HBITMAP bitmap;
+	int y;
+	uint8 cache_id, cache_idx_low, width, height, Bpp;
+	uint16 cache_idx, bufsize;
+	uint8 *data, *bmpdata, *bitmap_id;
+
+	bitmap_id = NULL;	/* prevent compiler warning */
+	cache_id = flags & ID_MASK;
+	Bpp = ((flags & MODE_MASK) >> MODE_SHIFT) - 2;
+
+	if (flags & PERSIST)
+	{
+		in_uint8p(s, bitmap_id, 8);
+	}
+
+	if (flags & SQUARE)
+	{
+		in_uint8(s, width);
+		height = width;
+	}
+	else
+	{
+		in_uint8(s, width);
+		in_uint8(s, height);
+	}
+
+	in_uint16_be(s, bufsize);
+	bufsize &= BUFSIZE_MASK;
+	in_uint8(s, cache_idx);
+
+	if (cache_idx & LONG_FORMAT)
+	{
+		in_uint8(s, cache_idx_low);
+		cache_idx = ((cache_idx ^ LONG_FORMAT) << 8) + cache_idx_low;
+	}
+
+	in_uint8p(s, data, bufsize);
+
+	DEBUG(("BMPCACHE2(compr=%d,flags=%x,cx=%d,cy=%d,id=%d,idx=%d,Bpp=%d,bs=%d)\n",
+	       compressed, flags, width, height, cache_id, cache_idx, Bpp, bufsize));
+
+	bmpdata = (uint8 *) xmalloc(width * height * Bpp);
+
+	if (compressed)
+	{
+		if (!bitmap_decompress(bmpdata, width, height, data, bufsize, Bpp))
+		{
+			DEBUG(("Failed to decompress bitmap data\n"));
+			xfree(bmpdata);
+			return;
+		}
+	}
+	else
+	{
+		for (y = 0; y < height; y++)
+			memcpy(&bmpdata[(height - y - 1) * (width * Bpp)],
+			       &data[y * (width * Bpp)], width * Bpp);
+	}
+
+	bitmap = ui_create_bitmap(width, height, bmpdata);
+
+	if (bitmap)
+	{
+		cache_put_bitmap(cache_id, cache_idx, bitmap);
+		if (flags & PERSIST)
+			pstcache_save_bitmap(cache_id, cache_idx, bitmap_id, width, height,
+					     width * height * Bpp, bmpdata);
+	}
+	else
+	{
+		DEBUG(("process_bmpcache2: ui_create_bitmap failed\n"));
+	}
+
+	xfree(bmpdata);
+}
+
+/* Process a colourmap cache order */
+static void
+process_colcache(STREAM s)
+{
+	COLOURENTRY *entry;
+	COLOURMAP map;
+	RD_HCOLOURMAP hmap;
+	uint8 cache_id;
+	int i;
+
+	in_uint8(s, cache_id);
+	in_uint16_le(s, map.ncolours);
+
+	map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
+
+	for (i = 0; i < map.ncolours; i++)
+	{
+		entry = &map.colours[i];
+		in_uint8(s, entry->blue);
+		in_uint8(s, entry->green);
+		in_uint8(s, entry->red);
+		in_uint8s(s, 1);	/* pad */
+	}
+
+	DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id, map.ncolours));
+
+	hmap = ui_create_colourmap(&map);
+
+	if (cache_id)
+		ui_set_colourmap(hmap);
+
+	xfree(map.colours);
+}
+
+/* Process a font cache order */
+static void
+process_fontcache(STREAM s)
+{
+	RD_HGLYPH bitmap;
+	uint8 font, nglyphs;
+	uint16 character, offset, baseline, width, height;
+	int i, datasize;
+	uint8 *data;
+
+	in_uint8(s, font);
+	in_uint8(s, nglyphs);
+
+	DEBUG(("FONTCACHE(font=%d,n=%d)\n", font, nglyphs));
+
+	for (i = 0; i < nglyphs; i++)
+	{
+		in_uint16_le(s, character);
+		in_uint16_le(s, offset);
+		in_uint16_le(s, baseline);
+		in_uint16_le(s, width);
+		in_uint16_le(s, height);
+
+		datasize = (height * ((width + 7) / 8) + 3) & ~3;
+		in_uint8p(s, data, datasize);
+
+		bitmap = ui_create_glyph(width, height, data);
+		cache_put_font(font, character, offset, baseline, width, height, bitmap);
+	}
+}
+
+static void
+process_compressed_8x8_brush_data(uint8 * in, uint8 * out, int Bpp)
+{
+	int x, y, pal_index, in_index, shift, do2, i;
+	uint8 *pal;
+
+	in_index = 0;
+	pal = in + 16;
+	/* read it bottom up */
+	for (y = 7; y >= 0; y--)
+	{
+		/* 2 bytes per row */
+		x = 0;
+		for (do2 = 0; do2 < 2; do2++)
+		{
+			/* 4 pixels per byte */
+			shift = 6;
+			while (shift >= 0)
+			{
+				pal_index = (in[in_index] >> shift) & 3;
+				/* size of palette entries depends on Bpp */
+				for (i = 0; i < Bpp; i++)
+				{
+					out[(y * 8 + x) * Bpp + i] = pal[pal_index * Bpp + i];
+				}
+				x++;
+				shift -= 2;
+			}
+			in_index++;
+		}
+	}
+}
+
+/* Process a brush cache order */
+static void
+process_brushcache(STREAM s, uint16 flags)
+{
+	BRUSHDATA brush_data;
+	uint8 cache_idx, colour_code, width, height, size, type;
+	uint8 *comp_brush;
+	int index;
+	int Bpp;
+
+	in_uint8(s, cache_idx);
+	in_uint8(s, colour_code);
+	in_uint8(s, width);
+	in_uint8(s, height);
+	in_uint8(s, type);	/* type, 0x8x = cached */
+	in_uint8(s, size);
+
+	DEBUG(("BRUSHCACHE(idx=%d,wd=%d,ht=%d,sz=%d)\n", cache_idx, width, height, size));
+
+	if ((width == 8) && (height == 8))
+	{
+		if (colour_code == 1)
+		{
+			brush_data.colour_code = 1;
+			brush_data.data_size = 8;
+			brush_data.data = xmalloc(8);
+			if (size == 8)
+			{
+				/* read it bottom up */
+				for (index = 7; index >= 0; index--)
+				{
+					in_uint8(s, brush_data.data[index]);
+				}
+			}
+			else
+			{
+				warning("incompatible brush, colour_code %d size %d\n", colour_code,
+					size);
+			}
+			cache_put_brush_data(1, cache_idx, &brush_data);
+		}
+		else if ((colour_code >= 3) && (colour_code <= 6))
+		{
+			Bpp = colour_code - 2;
+			brush_data.colour_code = colour_code;
+			brush_data.data_size = 8 * 8 * Bpp;
+			brush_data.data = xmalloc(8 * 8 * Bpp);
+			if (size == 16 + 4 * Bpp)
+			{
+				in_uint8p(s, comp_brush, 16 + 4 * Bpp);
+				process_compressed_8x8_brush_data(comp_brush, brush_data.data, Bpp);
+			}
+			else
+			{
+				in_uint8a(s, brush_data.data, 8 * 8 * Bpp);
+			}
+			cache_put_brush_data(colour_code, cache_idx, &brush_data);
+		}
+		else
+		{
+			warning("incompatible brush, colour_code %d size %d\n", colour_code, size);
+		}
+	}
+	else
+	{
+		warning("incompatible brush, width height %d %d\n", width, height);
+	}
+}
+
+/* Process a secondary order */
+static void
+process_secondary_order(STREAM s)
+{
+	/* The length isn't calculated correctly by the server.
+	 * For very compact orders the length becomes negative
+	 * so a signed integer must be used. */
+	uint16 length;
+	uint16 flags;
+	uint8 type;
+	uint8 *next_order;
+
+	in_uint16_le(s, length);
+	in_uint16_le(s, flags);	/* used by bmpcache2 */
+	in_uint8(s, type);
+
+	next_order = s->p + (sint16) length + 7;
+
+	switch (type)
+	{
+		case RDP_ORDER_RAW_BMPCACHE:
+			process_raw_bmpcache(s);
+			break;
+
+		case RDP_ORDER_COLCACHE:
+			process_colcache(s);
+			break;
+
+		case RDP_ORDER_BMPCACHE:
+			process_bmpcache(s);
+			break;
+
+		case RDP_ORDER_FONTCACHE:
+			process_fontcache(s);
+			break;
+
+		case RDP_ORDER_RAW_BMPCACHE2:
+			process_bmpcache2(s, flags, False);	/* uncompressed */
+			break;
+
+		case RDP_ORDER_BMPCACHE2:
+			process_bmpcache2(s, flags, True);	/* compressed */
+			break;
+
+		case RDP_ORDER_BRUSHCACHE:
+			process_brushcache(s, flags);
+			break;
+
+		default:
+			unimpl("secondary order %d\n", type);
+	}
+
+	s->p = next_order;
+}
+
+/* Process an order PDU */
+void
+process_orders(STREAM s, uint16 num_orders)
+{
+	RDP_ORDER_STATE *os = &g_order_state;
+	uint32 present;
+	uint8 order_flags;
+	int size, processed = 0;
+	RD_BOOL delta;
+
+	while (processed < num_orders)
+	{
+		in_uint8(s, order_flags);
+
+		if (!(order_flags & RDP_ORDER_STANDARD))
+		{
+			error("order parsing failed\n");
+			break;
+		}
+
+		if (order_flags & RDP_ORDER_SECONDARY)
+		{
+			process_secondary_order(s);
+		}
+		else
+		{
+			if (order_flags & RDP_ORDER_CHANGE)
+			{
+				in_uint8(s, os->order_type);
+			}
+
+			switch (os->order_type)
+			{
+				case RDP_ORDER_TRIBLT:
+				case RDP_ORDER_TEXT2:
+					size = 3;
+					break;
+
+				case RDP_ORDER_PATBLT:
+				case RDP_ORDER_MEMBLT:
+				case RDP_ORDER_LINE:
+				case RDP_ORDER_POLYGON2:
+				case RDP_ORDER_ELLIPSE2:
+					size = 2;
+					break;
+
+				default:
+					size = 1;
+			}
+
+			rdp_in_present(s, &present, order_flags, size);
+
+			if (order_flags & RDP_ORDER_BOUNDS)
+			{
+				if (!(order_flags & RDP_ORDER_LASTBOUNDS))
+					rdp_parse_bounds(s, &os->bounds);
+
+				ui_set_clip(os->bounds.left,
+					    os->bounds.top,
+					    os->bounds.right -
+					    os->bounds.left + 1,
+					    os->bounds.bottom - os->bounds.top + 1);
+			}
+
+			delta = order_flags & RDP_ORDER_DELTA;
+
+			switch (os->order_type)
+			{
+				case RDP_ORDER_DESTBLT:
+					process_destblt(s, &os->destblt, present, delta);
+					break;
+
+				case RDP_ORDER_PATBLT:
+					process_patblt(s, &os->patblt, present, delta);
+					break;
+
+				case RDP_ORDER_SCREENBLT:
+					process_screenblt(s, &os->screenblt, present, delta);
+					break;
+
+				case RDP_ORDER_LINE:
+					process_line(s, &os->line, present, delta);
+					break;
+
+				case RDP_ORDER_RECT:
+					process_rect(s, &os->rect, present, delta);
+					break;
+
+				case RDP_ORDER_DESKSAVE:
+					process_desksave(s, &os->desksave, present, delta);
+					break;
+
+				case RDP_ORDER_MEMBLT:
+					process_memblt(s, &os->memblt, present, delta);
+					break;
+
+				case RDP_ORDER_TRIBLT:
+					process_triblt(s, &os->triblt, present, delta);
+					break;
+
+				case RDP_ORDER_POLYGON:
+					process_polygon(s, &os->polygon, present, delta);
+					break;
+
+				case RDP_ORDER_POLYGON2:
+					process_polygon2(s, &os->polygon2, present, delta);
+					break;
+
+				case RDP_ORDER_POLYLINE:
+					process_polyline(s, &os->polyline, present, delta);
+					break;
+
+				case RDP_ORDER_ELLIPSE:
+					process_ellipse(s, &os->ellipse, present, delta);
+					break;
+
+				case RDP_ORDER_ELLIPSE2:
+					process_ellipse2(s, &os->ellipse2, present, delta);
+					break;
+
+				case RDP_ORDER_TEXT2:
+					process_text2(s, &os->text2, present, delta);
+					break;
+
+				default:
+					unimpl("order %d\n", os->order_type);
+					return;
+			}
+
+			if (order_flags & RDP_ORDER_BOUNDS)
+				ui_reset_clip();
+		}
+
+		processed++;
+	}
+#if 0
+	/* not true when RDP_COMPRESSION is set */
+	if (s->p != g_next_packet)
+		error("%d bytes remaining\n", (int) (g_next_packet - s->p));
+#endif
+
+}
+
+/* Reset order state */
+void
+reset_order_state(void)
+{
+	memset(&g_order_state, 0, sizeof(g_order_state));
+	g_order_state.order_type = RDP_ORDER_PATBLT;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/orders.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/orders.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/orders.h	(revision 55121)
@@ -0,0 +1,367 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   RDP order processing
+   Copyright (C) Matthew Chapman 1999-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define RDP_ORDER_STANDARD   0x01
+#define RDP_ORDER_SECONDARY  0x02
+#define RDP_ORDER_BOUNDS     0x04
+#define RDP_ORDER_CHANGE     0x08
+#define RDP_ORDER_DELTA      0x10
+#define RDP_ORDER_LASTBOUNDS 0x20
+#define RDP_ORDER_SMALL      0x40
+#define RDP_ORDER_TINY       0x80
+
+enum RDP_ORDER_TYPE
+{
+	RDP_ORDER_DESTBLT = 0,
+	RDP_ORDER_PATBLT = 1,
+	RDP_ORDER_SCREENBLT = 2,
+	RDP_ORDER_LINE = 9,
+	RDP_ORDER_RECT = 10,
+	RDP_ORDER_DESKSAVE = 11,
+	RDP_ORDER_MEMBLT = 13,
+	RDP_ORDER_TRIBLT = 14,
+	RDP_ORDER_POLYGON = 20,
+	RDP_ORDER_POLYGON2 = 21,
+	RDP_ORDER_POLYLINE = 22,
+	RDP_ORDER_ELLIPSE = 25,
+	RDP_ORDER_ELLIPSE2 = 26,
+	RDP_ORDER_TEXT2 = 27
+};
+
+enum RDP_SECONDARY_ORDER_TYPE
+{
+	RDP_ORDER_RAW_BMPCACHE = 0,
+	RDP_ORDER_COLCACHE = 1,
+	RDP_ORDER_BMPCACHE = 2,
+	RDP_ORDER_FONTCACHE = 3,
+	RDP_ORDER_RAW_BMPCACHE2 = 4,
+	RDP_ORDER_BMPCACHE2 = 5,
+	RDP_ORDER_BRUSHCACHE = 7
+};
+
+typedef struct _DESTBLT_ORDER
+{
+	sint16 x;
+	sint16 y;
+	sint16 cx;
+	sint16 cy;
+	uint8 opcode;
+
+}
+DESTBLT_ORDER;
+
+typedef struct _PATBLT_ORDER
+{
+	sint16 x;
+	sint16 y;
+	sint16 cx;
+	sint16 cy;
+	uint8 opcode;
+	uint32 bgcolour;
+	uint32 fgcolour;
+	BRUSH brush;
+
+}
+PATBLT_ORDER;
+
+typedef struct _SCREENBLT_ORDER
+{
+	sint16 x;
+	sint16 y;
+	sint16 cx;
+	sint16 cy;
+	uint8 opcode;
+	sint16 srcx;
+	sint16 srcy;
+
+}
+SCREENBLT_ORDER;
+
+typedef struct _LINE_ORDER
+{
+	uint16 mixmode;
+	sint16 startx;
+	sint16 starty;
+	sint16 endx;
+	sint16 endy;
+	uint32 bgcolour;
+	uint8 opcode;
+	PEN pen;
+
+}
+LINE_ORDER;
+
+typedef struct _RECT_ORDER
+{
+	sint16 x;
+	sint16 y;
+	sint16 cx;
+	sint16 cy;
+	uint32 colour;
+
+}
+RECT_ORDER;
+
+typedef struct _DESKSAVE_ORDER
+{
+	uint32 offset;
+	sint16 left;
+	sint16 top;
+	sint16 right;
+	sint16 bottom;
+	uint8 action;
+
+}
+DESKSAVE_ORDER;
+
+typedef struct _TRIBLT_ORDER
+{
+	uint8 colour_table;
+	uint8 cache_id;
+	sint16 x;
+	sint16 y;
+	sint16 cx;
+	sint16 cy;
+	uint8 opcode;
+	sint16 srcx;
+	sint16 srcy;
+	uint32 bgcolour;
+	uint32 fgcolour;
+	BRUSH brush;
+	uint16 cache_idx;
+	uint16 unknown;
+
+}
+TRIBLT_ORDER;
+
+typedef struct _MEMBLT_ORDER
+{
+	uint8 colour_table;
+	uint8 cache_id;
+	sint16 x;
+	sint16 y;
+	sint16 cx;
+	sint16 cy;
+	uint8 opcode;
+	sint16 srcx;
+	sint16 srcy;
+	uint16 cache_idx;
+
+}
+MEMBLT_ORDER;
+
+#define MAX_DATA 256
+
+typedef struct _POLYGON_ORDER
+{
+	sint16 x;
+	sint16 y;
+	uint8 opcode;
+	uint8 fillmode;
+	uint32 fgcolour;
+	uint8 npoints;
+	uint8 datasize;
+	uint8 data[MAX_DATA];
+
+}
+POLYGON_ORDER;
+
+typedef struct _POLYGON2_ORDER
+{
+	sint16 x;
+	sint16 y;
+	uint8 opcode;
+	uint8 fillmode;
+	uint32 bgcolour;
+	uint32 fgcolour;
+	BRUSH brush;
+	uint8 npoints;
+	uint8 datasize;
+	uint8 data[MAX_DATA];
+
+}
+POLYGON2_ORDER;
+
+typedef struct _POLYLINE_ORDER
+{
+	sint16 x;
+	sint16 y;
+	uint8 opcode;
+	uint32 fgcolour;
+	uint8 lines;
+	uint8 datasize;
+	uint8 data[MAX_DATA];
+
+}
+POLYLINE_ORDER;
+
+typedef struct _ELLIPSE_ORDER
+{
+	sint16 left;
+	sint16 top;
+	sint16 right;
+	sint16 bottom;
+	uint8 opcode;
+	uint8 fillmode;
+	uint32 fgcolour;
+
+}
+ELLIPSE_ORDER;
+
+typedef struct _ELLIPSE2_ORDER
+{
+	sint16 left;
+	sint16 top;
+	sint16 right;
+	sint16 bottom;
+	uint8 opcode;
+	uint8 fillmode;
+	BRUSH brush;
+	uint32 bgcolour;
+	uint32 fgcolour;
+
+}
+ELLIPSE2_ORDER;
+
+#define MAX_TEXT 256
+
+typedef struct _TEXT2_ORDER
+{
+	uint8 font;
+	uint8 flags;
+	uint8 opcode;
+	uint8 mixmode;
+	uint32 bgcolour;
+	uint32 fgcolour;
+	sint16 clipleft;
+	sint16 cliptop;
+	sint16 clipright;
+	sint16 clipbottom;
+	sint16 boxleft;
+	sint16 boxtop;
+	sint16 boxright;
+	sint16 boxbottom;
+	BRUSH brush;
+	sint16 x;
+	sint16 y;
+	uint8 length;
+	uint8 text[MAX_TEXT];
+
+}
+TEXT2_ORDER;
+
+typedef struct _RDP_ORDER_STATE
+{
+	uint8 order_type;
+	BOUNDS bounds;
+
+	DESTBLT_ORDER destblt;
+	PATBLT_ORDER patblt;
+	SCREENBLT_ORDER screenblt;
+	LINE_ORDER line;
+	RECT_ORDER rect;
+	DESKSAVE_ORDER desksave;
+	MEMBLT_ORDER memblt;
+	TRIBLT_ORDER triblt;
+	POLYGON_ORDER polygon;
+	POLYGON2_ORDER polygon2;
+	POLYLINE_ORDER polyline;
+	ELLIPSE_ORDER ellipse;
+	ELLIPSE2_ORDER ellipse2;
+	TEXT2_ORDER text2;
+
+}
+RDP_ORDER_STATE;
+
+typedef struct _RDP_RAW_BMPCACHE_ORDER
+{
+	uint8 cache_id;
+	uint8 pad1;
+	uint8 width;
+	uint8 height;
+	uint8 bpp;
+	uint16 bufsize;
+	uint16 cache_idx;
+	uint8 *data;
+
+}
+RDP_RAW_BMPCACHE_ORDER;
+
+typedef struct _RDP_BMPCACHE_ORDER
+{
+	uint8 cache_id;
+	uint8 pad1;
+	uint8 width;
+	uint8 height;
+	uint8 bpp;
+	uint16 bufsize;
+	uint16 cache_idx;
+	uint16 pad2;
+	uint16 size;
+	uint16 row_size;
+	uint16 final_size;
+	uint8 *data;
+
+}
+RDP_BMPCACHE_ORDER;
+
+/* RDP_BMPCACHE2_ORDER */
+#define ID_MASK			0x0007
+#define MODE_MASK		0x0038
+#define SQUARE			0x0080
+#define PERSIST			0x0100
+#define FLAG_51_UNKNOWN		0x0800
+
+#define MODE_SHIFT		3
+
+#define LONG_FORMAT		0x80
+#define BUFSIZE_MASK		0x3FFF	/* or 0x1FFF? */
+
+#define MAX_GLYPH 32
+
+typedef struct _RDP_FONT_GLYPH
+{
+	uint16 character;
+	uint16 unknown;
+	uint16 baseline;
+	uint16 width;
+	uint16 height;
+	uint8 data[MAX_GLYPH];
+
+}
+RDP_FONT_GLYPH;
+
+#define MAX_GLYPHS 256
+
+typedef struct _RDP_FONTCACHE_ORDER
+{
+	uint8 font;
+	uint8 nglyphs;
+	RDP_FONT_GLYPH glyphs[MAX_GLYPHS];
+
+}
+RDP_FONTCACHE_ORDER;
+
+typedef struct _RDP_COLCACHE_ORDER
+{
+	uint8 cache_id;
+	COLOURMAP map;
+
+}
+RDP_COLCACHE_ORDER;
Index: /trunk/src/VBox/RDP/client-1.8.3/parallel.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/parallel.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/parallel.c	(revision 55121)
@@ -0,0 +1,189 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#define	MAX_PARALLEL_DEVICES		1
+
+#define FILE_DEVICE_PARALLEL		0x22
+
+#define IOCTL_PAR_QUERY_RAW_DEVICE_ID	0x0c
+
+#include "rdesktop.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#if defined(__linux__)
+#include <linux/lp.h>
+#endif
+
+extern RDPDR_DEVICE g_rdpdr_device[];
+
+
+/* Enumeration of devices from rdesktop.c        */
+/* returns numer of units found and initialized. */
+/* optarg looks like ':LPT1=/dev/lp0'            */
+/* when it arrives to this function.             */
+int
+parallel_enum_devices(uint32 * id, char *optarg)
+{
+	PARALLEL_DEVICE *ppar_info;
+
+	char *pos = optarg;
+	char *pos2;
+	int count = 0;
+
+	/* skip the first colon */
+	optarg++;
+	while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
+	{
+		ppar_info = (PARALLEL_DEVICE *) xmalloc(sizeof(PARALLEL_DEVICE));
+
+		pos2 = next_arg(optarg, '=');
+		strcpy(g_rdpdr_device[*id].name, optarg);
+
+		toupper_str(g_rdpdr_device[*id].name);
+
+		g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
+		strcpy(g_rdpdr_device[*id].local_path, pos2);
+		printf("PARALLEL %s to %s\n", optarg, pos2);
+
+		/* set device type */
+		g_rdpdr_device[*id].device_type = DEVICE_TYPE_PARALLEL;
+		g_rdpdr_device[*id].pdevice_data = (void *) ppar_info;
+		g_rdpdr_device[*id].handle = 0;
+		count++;
+		(*id)++;
+
+		optarg = pos;
+	}
+	return count;
+}
+
+static RD_NTSTATUS
+parallel_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,
+		uint32 flags, char *filename, RD_NTHANDLE * handle)
+{
+	int parallel_fd;
+
+	parallel_fd = open(g_rdpdr_device[device_id].local_path, O_RDWR);
+	if (parallel_fd == -1)
+	{
+		perror("open");
+		return RD_STATUS_ACCESS_DENIED;
+	}
+
+	/* all read and writes should be non blocking */
+	if (fcntl(parallel_fd, F_SETFL, O_NONBLOCK) == -1)
+		perror("fcntl");
+
+#if defined(LPABORT)
+	/* Retry on errors */
+	ioctl(parallel_fd, LPABORT, (int) 1);
+#endif
+
+	g_rdpdr_device[device_id].handle = parallel_fd;
+
+	*handle = parallel_fd;
+
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+parallel_close(RD_NTHANDLE handle)
+{
+	int i = get_device_index(handle);
+	if (i >= 0)
+		g_rdpdr_device[i].handle = 0;
+	close(handle);
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+parallel_read(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
+{
+	*result = read(handle, data, length);
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+parallel_write(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
+{
+	int rc = RD_STATUS_SUCCESS;
+
+	int n = write(handle, data, length);
+	if (n < 0)
+	{
+#if defined(LPGETSTATUS)
+		int status;
+#endif
+
+		*result = 0;
+		switch (errno)
+		{
+			case EAGAIN:
+				rc = RD_STATUS_DEVICE_OFF_LINE;
+			case ENOSPC:
+				rc = RD_STATUS_DEVICE_PAPER_EMPTY;
+			case EIO:
+				rc = RD_STATUS_DEVICE_OFF_LINE;
+			default:
+				rc = RD_STATUS_DEVICE_POWERED_OFF;
+		}
+#if defined(LPGETSTATUS)
+		if (ioctl(handle, LPGETSTATUS, &status) == 0)
+		{
+			/* coming soon: take care for the printer status */
+			printf("parallel_write: status = %d, errno = %d\n", status, errno);
+		}
+#endif
+	}
+	*result = n;
+	return rc;
+}
+
+static RD_NTSTATUS
+parallel_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
+{
+	if ((request >> 16) != FILE_DEVICE_PARALLEL)
+		return RD_STATUS_INVALID_PARAMETER;
+
+	/* extract operation */
+	request >>= 2;
+	request &= 0xfff;
+
+	printf("PARALLEL IOCTL %d: ", request);
+
+	switch (request)
+	{
+		case IOCTL_PAR_QUERY_RAW_DEVICE_ID:
+
+		default:
+
+			printf("\n");
+			unimpl("UNKNOWN IOCTL %d\n", request);
+	}
+	return RD_STATUS_SUCCESS;
+}
+
+DEVICE_FNS parallel_fns = {
+	parallel_create,
+	parallel_close,
+	parallel_read,
+	parallel_write,
+	parallel_device_control
+};
Index: /trunk/src/VBox/RDP/client-1.8.3/parse.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/parse.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/parse.h	(revision 55121)
@@ -0,0 +1,97 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   Parsing primitives
+   Copyright (C) Matthew Chapman 1999-2008
+   Copyright 2012 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* Parser state */
+typedef struct stream
+{
+	unsigned char *p;
+	unsigned char *end;
+	unsigned char *data;
+	unsigned int size;
+
+	/* Offsets of various headers */
+	unsigned char *iso_hdr;
+	unsigned char *mcs_hdr;
+	unsigned char *sec_hdr;
+	unsigned char *rdp_hdr;
+	unsigned char *channel_hdr;
+
+}
+ *STREAM;
+
+#define s_push_layer(s,h,n)	{ (s)->h = (s)->p; (s)->p += n; }
+#define s_pop_layer(s,h)	(s)->p = (s)->h;
+#define s_mark_end(s)		(s)->end = (s)->p;
+#define s_check(s)		((s)->p <= (s)->end)
+#define s_check_rem(s,n)	((s)->p + n <= (s)->end)
+#define s_check_end(s)		((s)->p == (s)->end)
+#define s_length(s)		((s)->end - (s)->data)
+#define s_reset(s)		((s)->end = (s)->p = (s)->data)
+
+#if defined(L_ENDIAN) && !defined(NEED_ALIGN)
+#define in_uint16_le(s,v)	{ v = *(uint16 *)((s)->p); (s)->p += 2; }
+#define in_uint32_le(s,v)	{ v = *(uint32 *)((s)->p); (s)->p += 4; }
+#define out_uint16_le(s,v)	{ *(uint16 *)((s)->p) = v; (s)->p += 2; }
+#define out_uint32_le(s,v)	{ *(uint32 *)((s)->p) = v; (s)->p += 4; }
+
+#else
+#define in_uint16_le(s,v)	{ v = *((s)->p++); v += *((s)->p++) << 8; }
+#define in_uint32_le(s,v)	{ in_uint16_le(s,v) \
+				v += *((s)->p++) << 16; v += *((s)->p++) << 24; }
+#define out_uint16_le(s,v)	{ *((s)->p++) = (v) & 0xff; *((s)->p++) = ((v) >> 8) & 0xff; }
+#define out_uint32_le(s,v)	{ out_uint16_le(s, (v) & 0xffff); out_uint16_le(s, ((v) >> 16) & 0xffff); }
+#endif
+
+#if defined(B_ENDIAN) && !defined(NEED_ALIGN)
+#define in_uint16_be(s,v)	{ v = *(uint16 *)((s)->p); (s)->p += 2; }
+#define in_uint32_be(s,v)	{ v = *(uint32 *)((s)->p); (s)->p += 4; }
+#define out_uint16_be(s,v)	{ *(uint16 *)((s)->p) = v; (s)->p += 2; }
+#define out_uint32_be(s,v)	{ *(uint32 *)((s)->p) = v; (s)->p += 4; }
+
+#define B_ENDIAN_PREFERRED
+#define in_uint16(s,v)		in_uint16_be(s,v)
+#define in_uint32(s,v)		in_uint32_be(s,v)
+#define out_uint16(s,v)		out_uint16_be(s,v)
+#define out_uint32(s,v)		out_uint32_be(s,v)
+
+#else
+#define in_uint16_be(s,v)	{ v = *((s)->p++); next_be(s,v); }
+#define in_uint32_be(s,v)	{ in_uint16_be(s,v); next_be(s,v); next_be(s,v); }
+#define out_uint16_be(s,v)	{ *((s)->p++) = ((v) >> 8) & 0xff; *((s)->p++) = (v) & 0xff; }
+#define out_uint32_be(s,v)	{ out_uint16_be(s, ((v) >> 16) & 0xffff); out_uint16_be(s, (v) & 0xffff); }
+#endif
+
+#ifndef B_ENDIAN_PREFERRED
+#define in_uint16(s,v)		in_uint16_le(s,v)
+#define in_uint32(s,v)		in_uint32_le(s,v)
+#define out_uint16(s,v)		out_uint16_le(s,v)
+#define out_uint32(s,v)		out_uint32_le(s,v)
+#endif
+
+#define in_uint8(s,v)		v = *((s)->p++);
+#define in_uint8p(s,v,n)	{ v = (s)->p; (s)->p += n; }
+#define in_uint8a(s,v,n)	{ memcpy(v,(s)->p,n); (s)->p += n; }
+#define in_uint8s(s,n)		(s)->p += n;
+#define out_uint8(s,v)		*((s)->p++) = v;
+#define out_uint8p(s,v,n)	{ memcpy((s)->p,v,n); (s)->p += n; }
+#define out_uint8a(s,v,n)	out_uint8p(s,v,n);
+#define out_uint8s(s,n)		{ memset((s)->p,0,n); (s)->p += n; }
+
+#define next_be(s,v)		v = ((v) << 8) + *((s)->p++);
Index: /trunk/src/VBox/RDP/client-1.8.3/printer.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/printer.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/printer.c	(revision 55121)
@@ -0,0 +1,163 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+
+extern RDPDR_DEVICE g_rdpdr_device[];
+
+static PRINTER *
+get_printer_data(RD_NTHANDLE handle)
+{
+	int index;
+
+	for (index = 0; index < RDPDR_MAX_DEVICES; index++)
+	{
+		if (handle == g_rdpdr_device[index].handle)
+			return (PRINTER *) g_rdpdr_device[index].pdevice_data;
+	}
+	return NULL;
+}
+
+int
+printer_enum_devices(uint32 * id, char *optarg)
+{
+	PRINTER *pprinter_data;
+
+	char *pos = optarg;
+	char *pos2;
+	int count = 0;
+	int already = 0;
+
+	/* we need to know how many printers we've already set up
+	   supplied from other -r flags than this one. */
+	while (count < *id)
+	{
+		if (g_rdpdr_device[count].device_type == DEVICE_TYPE_PRINTER)
+			already++;
+		count++;
+	}
+
+	count = 0;
+
+	if (*optarg == ':')
+		optarg++;
+
+	while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
+	{
+		pprinter_data = (PRINTER *) xmalloc(sizeof(PRINTER));
+
+		strcpy(g_rdpdr_device[*id].name, "PRN");
+		strcat(g_rdpdr_device[*id].name, l_to_a(already + count + 1, 10));
+
+		/* first printer is set as default printer */
+		if ((already + count) == 0)
+			pprinter_data->default_printer = True;
+		else
+			pprinter_data->default_printer = False;
+
+		pos2 = next_arg(optarg, '=');
+		if (*optarg == (char) 0x00)
+			pprinter_data->printer = "mydeskjet";	/* set default */
+		else
+		{
+			pprinter_data->printer = xmalloc(strlen(optarg) + 1);
+			strcpy(pprinter_data->printer, optarg);
+		}
+
+		if (!pos2 || (*pos2 == (char) 0x00))
+			pprinter_data->driver = "MS Publisher Imagesetter";	/* no printer driver supplied set default */
+		else
+		{
+			pprinter_data->driver = xmalloc(strlen(pos2) + 1);
+			strcpy(pprinter_data->driver, pos2);
+		}
+
+		printf("PRINTER %s to %s driver %s\n", g_rdpdr_device[*id].name,
+		       pprinter_data->printer, pprinter_data->driver);
+		g_rdpdr_device[*id].device_type = DEVICE_TYPE_PRINTER;
+		g_rdpdr_device[*id].pdevice_data = (void *) pprinter_data;
+		count++;
+		(*id)++;
+
+		optarg = pos;
+	}
+	return count;
+}
+
+static RD_NTSTATUS
+printer_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition, uint32 flags,
+	       char *filename, RD_NTHANDLE * handle)
+{
+	char cmd[256];
+	PRINTER *pprinter_data;
+
+	pprinter_data = (PRINTER *) g_rdpdr_device[device_id].pdevice_data;
+
+	/* default printer name use default printer queue as well in unix */
+	if (strncmp(pprinter_data->printer, "mydeskjet", strlen(pprinter_data->printer)) == 0)
+	{
+		pprinter_data->printer_fp = popen("lpr", "w");
+	}
+	else
+	{
+		sprintf(cmd, "lpr -P %s", pprinter_data->printer);
+		pprinter_data->printer_fp = popen(cmd, "w");
+	}
+
+	g_rdpdr_device[device_id].handle = fileno(pprinter_data->printer_fp);
+	*handle = g_rdpdr_device[device_id].handle;
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+printer_close(RD_NTHANDLE handle)
+{
+	int i = get_device_index(handle);
+	if (i >= 0)
+	{
+		PRINTER *pprinter_data = g_rdpdr_device[i].pdevice_data;
+		if (pprinter_data)
+			pclose(pprinter_data->printer_fp);
+		g_rdpdr_device[i].handle = 0;
+	}
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+printer_write(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
+{
+	PRINTER *pprinter_data;
+
+	pprinter_data = get_printer_data(handle);
+	*result = length * fwrite(data, length, 1, pprinter_data->printer_fp);
+
+	if (ferror(pprinter_data->printer_fp))
+	{
+		*result = 0;
+		return RD_STATUS_INVALID_HANDLE;
+	}
+	return RD_STATUS_SUCCESS;
+}
+
+DEVICE_FNS printer_fns = {
+	printer_create,
+	printer_close,
+	NULL,			/* read */
+	printer_write,
+	NULL			/* device_control */
+};
Index: /trunk/src/VBox/RDP/client-1.8.3/printercache.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/printercache.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/printercache.c	(revision 55121)
@@ -0,0 +1,311 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Entrypoint and utility functions
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright (C) Jeroen Meijer <jeroen@oldambt7.com> 2003-2008
+   Copyright (C) Henrik Andersson <hean01@cendio.com> 2013
+   
+  
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* According to the W2K RDP Printer Redirection WhitePaper, a data
+ * blob is sent to the client after the configuration of the printer
+ * is changed at the server.
+ *
+ * This data blob is saved to the registry. The client returns this
+ * data blob in a new session with the printer announce data.
+ * The data is not interpreted by the client.
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include "rdesktop.h"
+
+static RD_BOOL
+printercache_mkdir(char *base, char *printer)
+{
+	char *path;
+
+	path = (char *) xmalloc(strlen(base) + sizeof("/.rdesktop/rdpdr/") + strlen(printer) + 1);
+
+	sprintf(path, "%s/.rdesktop", base);
+	if ((mkdir(path, 0700) == -1) && errno != EEXIST)
+	{
+		perror(path);
+		xfree(path);
+		return False;
+	}
+
+	strcat(path, "/rdpdr");
+	if ((mkdir(path, 0700) == -1) && errno != EEXIST)
+	{
+		perror(path);
+		xfree(path);
+		return False;
+	}
+
+	strcat(path, "/");
+	strcat(path, printer);
+	if ((mkdir(path, 0700) == -1) && errno != EEXIST)
+	{
+		perror(path);
+		xfree(path);
+		return False;
+	}
+
+	xfree(path);
+	return True;
+}
+
+static RD_BOOL
+printercache_unlink_blob(char *printer)
+{
+	char *path;
+	char *home;
+
+	if (printer == NULL)
+		return False;
+
+	home = getenv("HOME");
+	if (home == NULL)
+		return False;
+
+	path = (char *) xmalloc(strlen(home) + sizeof("/.rdesktop/rdpdr/") + strlen(printer) +
+				sizeof("/AutoPrinterCacheData") + 1);
+
+	sprintf(path, "%s/.rdesktop/rdpdr/%s/AutoPrinterCacheData", home, printer);
+
+	if (unlink(path) < 0)
+	{
+		xfree(path);
+		return False;
+	}
+
+	sprintf(path, "%s/.rdesktop/rdpdr/%s", home, printer);
+
+	if (rmdir(path) < 0)
+	{
+		xfree(path);
+		return False;
+	}
+
+	xfree(path);
+	return True;
+}
+
+
+static RD_BOOL
+printercache_rename_blob(char *printer, char *new_printer)
+{
+	char *printer_path;
+	char *new_printer_path;
+	int printer_maxlen;
+
+	char *home;
+
+	if (printer == NULL)
+		return False;
+
+	home = getenv("HOME");
+	if (home == NULL)
+		return False;
+
+	printer_maxlen =
+		(strlen(printer) >
+		 strlen(new_printer) ? strlen(printer) : strlen(new_printer)) + strlen(home) +
+		sizeof("/.rdesktop/rdpdr/") + 1;
+
+	printer_path = (char *) xmalloc(printer_maxlen);
+	new_printer_path = (char *) xmalloc(printer_maxlen);
+
+	sprintf(printer_path, "%s/.rdesktop/rdpdr/%s", home, printer);
+	sprintf(new_printer_path, "%s/.rdesktop/rdpdr/%s", home, new_printer);
+
+	printf("%s,%s\n", printer_path, new_printer_path);
+	if (rename(printer_path, new_printer_path) < 0)
+	{
+		xfree(printer_path);
+		xfree(new_printer_path);
+		return False;
+	}
+
+	xfree(printer_path);
+	xfree(new_printer_path);
+	return True;
+}
+
+
+int
+printercache_load_blob(char *printer_name, uint8 ** data)
+{
+	char *home, *path;
+	struct stat st;
+	int fd, length;
+
+	if (printer_name == NULL)
+		return 0;
+
+	*data = NULL;
+
+	home = getenv("HOME");
+	if (home == NULL)
+		return 0;
+
+	path = (char *) xmalloc(strlen(home) + sizeof("/.rdesktop/rdpdr/") + strlen(printer_name) +
+				sizeof("/AutoPrinterCacheData") + 1);
+	sprintf(path, "%s/.rdesktop/rdpdr/%s/AutoPrinterCacheData", home, printer_name);
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1)
+	{
+		xfree(path);
+		return 0;
+	}
+
+	if (fstat(fd, &st))
+	{
+		xfree(path);
+		return 0;
+	}
+
+	*data = (uint8 *) xmalloc(st.st_size);
+	length = read(fd, *data, st.st_size);
+	close(fd);
+	xfree(path);
+	return length;
+}
+
+static void
+printercache_save_blob(char *printer_name, uint8 * data, uint32 length)
+{
+	char *home, *path;
+	int fd;
+
+	if (printer_name == NULL)
+		return;
+
+	home = getenv("HOME");
+	if (home == NULL)
+		return;
+
+	if (!printercache_mkdir(home, printer_name))
+		return;
+
+	path = (char *) xmalloc(strlen(home) + sizeof("/.rdesktop/rdpdr/") + strlen(printer_name) +
+				sizeof("/AutoPrinterCacheData") + 1);
+	sprintf(path, "%s/.rdesktop/rdpdr/%s/AutoPrinterCacheData", home, printer_name);
+
+	fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+	if (fd == -1)
+	{
+		perror(path);
+		xfree(path);
+		return;
+	}
+
+	if (write(fd, data, length) != length)
+	{
+		perror(path);
+		unlink(path);
+	}
+
+	close(fd);
+	xfree(path);
+}
+
+void
+printercache_process(STREAM s)
+{
+	uint32 type, printer_length, driver_length, printer_unicode_length, blob_length;
+	char device_name[9], *printer, *driver;
+
+	printer = driver = NULL;
+
+	in_uint32_le(s, type);
+	switch (type)
+	{
+		case 4:	/* rename item */
+			in_uint8(s, printer_length);
+			in_uint8s(s, 0x3);	/* padding */
+			in_uint8(s, driver_length);
+			in_uint8s(s, 0x3);	/* padding */
+
+			/* NOTE - 'driver' doesn't contain driver, it contains the new printer name */
+
+			rdp_in_unistr(s, printer_length, &printer, &printer_length);
+			rdp_in_unistr(s, driver_length, &driver, &driver_length);
+
+			if (printer != NULL && driver != NULL)
+				printercache_rename_blob(printer, driver);
+
+			free(printer);
+			free(driver);
+			break;
+
+		case 3:	/* delete item */
+			in_uint8(s, printer_unicode_length);
+			in_uint8s(s, 0x3);	/* padding */
+			rdp_in_unistr(s, printer_unicode_length, &printer, &printer_unicode_length);
+			if (printer)
+				printercache_unlink_blob(printer);
+			free(printer);
+			break;
+
+		case 2:	/* save printer data */
+			in_uint32_le(s, printer_unicode_length);
+			in_uint32_le(s, blob_length);
+
+			if (printer_unicode_length < 2 * 255)
+			{
+				rdp_in_unistr(s, printer_unicode_length, &printer,
+					      &printer_unicode_length);
+				if (printer)
+					printercache_save_blob(printer, s->p, blob_length);
+				free(printer);
+			}
+			break;
+
+		case 1:	/* save device data */
+			in_uint8a(s, device_name, 5);	/* get LPTx/COMx name */
+
+			/* need to fetch this data so that we can get the length of the packet to store. */
+			in_uint8s(s, 0x2);	/* ??? */
+			in_uint8s(s, 0x2)	/* pad?? */
+				in_uint32_be(s, driver_length);
+			in_uint32_be(s, printer_length);
+			in_uint8s(s, 0x7)	/* pad?? */
+				/* next is driver in unicode */
+				/* next is printer in unicode */
+				/* TODO: figure out how to use this information when reconnecting */
+				/* actually - all we need to store is the driver and printer */
+				/* and figure out what the first word is. */
+				/* rewind stream so that we can save this blob   */
+				/* length is driver_length + printer_length + 19 */
+				/* rewind stream */
+				s->p = s->p - 19;
+
+			printercache_save_blob(device_name, s->p,
+					       driver_length + printer_length + 19);
+			break;
+		default:
+
+			unimpl("RDPDR Printer Cache Packet Type: %d\n", type);
+			break;
+	}
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/proto.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/proto.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/proto.h	(revision 55121)
@@ -0,0 +1,364 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Copyright (C) Matthew Chapman 1999-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef RDESKTOP_PROTO_H
+#define RDESKTOP_PROTO_H
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* *INDENT-ON* */
+/* utils.c */
+char *utils_string_escape(const char *str);
+char *utils_string_unescape(const char *str);
+int utils_locale_to_utf8(const char *src, size_t is, char *dest, size_t os);
+int utils_mkdir_safe(const char *path, int mask);
+int utils_mkdir_p(const char *path, int mask);
+/* bitmap.c */
+RD_BOOL bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp);
+/* cache.c */
+void cache_rebuild_bmpcache_linked_list(uint8 id, sint16 * idx, int count);
+void cache_bump_bitmap(uint8 id, uint16 idx, int bump);
+void cache_evict_bitmap(uint8 id);
+RD_HBITMAP cache_get_bitmap(uint8 id, uint16 idx);
+void cache_put_bitmap(uint8 id, uint16 idx, RD_HBITMAP bitmap);
+void cache_save_state(void);
+FONTGLYPH *cache_get_font(uint8 font, uint16 character);
+void cache_put_font(uint8 font, uint16 character, uint16 offset, uint16 baseline, uint16 width,
+		    uint16 height, RD_HGLYPH pixmap);
+DATABLOB *cache_get_text(uint8 cache_id);
+void cache_put_text(uint8 cache_id, void *data, int length);
+uint8 *cache_get_desktop(uint32 offset, int cx, int cy, int bytes_per_pixel);
+void cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel,
+		       uint8 * data);
+RD_HCURSOR cache_get_cursor(uint16 cache_idx);
+void cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor);
+BRUSHDATA *cache_get_brush_data(uint8 colour_code, uint8 idx);
+void cache_put_brush_data(uint8 colour_code, uint8 idx, BRUSHDATA * brush_data);
+/* channels.c */
+VCHANNEL *channel_register(char *name, uint32 flags, void (*callback) (STREAM));
+STREAM channel_init(VCHANNEL * channel, uint32 length);
+void channel_send(STREAM s, VCHANNEL * channel);
+void channel_process(STREAM s, uint16 mcs_channel);
+/* cliprdr.c */
+void cliprdr_send_simple_native_format_announce(uint32 format);
+void cliprdr_send_native_format_announce(uint8 * formats_data, uint32 formats_data_length);
+void cliprdr_send_data_request(uint32 format);
+void cliprdr_send_data(uint8 * data, uint32 length);
+void cliprdr_set_mode(const char *optarg);
+RD_BOOL cliprdr_init(void);
+/* ctrl.c */
+int ctrl_init(const char *user, const char *domain, const char *host);
+void ctrl_cleanup();
+RD_BOOL ctrl_is_slave();
+int ctrl_send_command(const char *cmd, const char *args);
+void ctrl_add_fds(int *n, fd_set * rfds);
+void ctrl_check_fds(fd_set * rfds, fd_set * wfds);
+
+/* disk.c */
+int disk_enum_devices(uint32 * id, char *optarg);
+RD_NTSTATUS disk_query_information(RD_NTHANDLE handle, uint32 info_class, STREAM out);
+RD_NTSTATUS disk_set_information(RD_NTHANDLE handle, uint32 info_class, STREAM in, STREAM out);
+RD_NTSTATUS disk_check_notify(RD_NTHANDLE handle);
+RD_NTSTATUS disk_create_notify(RD_NTHANDLE handle, uint32 info_class);
+RD_NTSTATUS disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out);
+RD_NTSTATUS disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREAM out);
+/* mppc.c */
+int mppc_expand(uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen);
+/* ewmhints.c */
+int get_current_workarea(uint32 * x, uint32 * y, uint32 * width, uint32 * height);
+void ewmh_init(void);
+/* iso.c */
+STREAM iso_init(int length);
+void iso_send(STREAM s);
+STREAM iso_recv(uint8 * rdpver);
+RD_BOOL iso_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect,
+		    uint32 * selected_protocol);
+void iso_disconnect(void);
+void iso_reset_state(void);
+/* cssp.c */
+RD_BOOL cssp_connect(char *server, char *user, char *domain, char *password, STREAM s);
+/* licence.c */
+void licence_process(STREAM s);
+/* mcs.c */
+STREAM mcs_init(int length);
+void mcs_send_to_channel(STREAM s, uint16 channel);
+void mcs_send(STREAM s);
+STREAM mcs_recv(uint16 * channel, uint8 * rdpver);
+RD_BOOL mcs_connect_start(char *server, char *username, char *domain, char *password,
+			  RD_BOOL reconnect, uint32 * selected_protocol);
+RD_BOOL mcs_connect_finalize(STREAM s);
+void mcs_disconnect(void);
+void mcs_reset_state(void);
+/* orders.c */
+void process_orders(STREAM s, uint16 num_orders);
+void reset_order_state(void);
+/* parallel.c */
+int parallel_enum_devices(uint32 * id, char *optarg);
+/* printer.c */
+int printer_enum_devices(uint32 * id, char *optarg);
+/* printercache.c */
+int printercache_load_blob(char *printer_name, uint8 ** data);
+void printercache_process(STREAM s);
+/* pstcache.c */
+void pstcache_touch_bitmap(uint8 cache_id, uint16 cache_idx, uint32 stamp);
+RD_BOOL pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx);
+RD_BOOL pstcache_save_bitmap(uint8 cache_id, uint16 cache_idx, uint8 * key, uint8 width,
+			     uint8 height, uint16 length, uint8 * data);
+int pstcache_enumerate(uint8 id, HASH_KEY * keylist);
+RD_BOOL pstcache_init(uint8 cache_id);
+/* rdesktop.c */
+int main(int argc, char *argv[]);
+void generate_random(uint8 * random);
+void *xmalloc(int size);
+void exit_if_null(void *ptr);
+char *xstrdup(const char *s);
+void *xrealloc(void *oldmem, size_t size);
+void xfree(void *mem);
+void error(char *format, ...);
+void warning(char *format, ...);
+void unimpl(char *format, ...);
+void hexdump(unsigned char *p, unsigned int len);
+char *next_arg(char *src, char needle);
+void toupper_str(char *p);
+RD_BOOL str_startswith(const char *s, const char *prefix);
+RD_BOOL str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler,
+			 void *data);
+RD_BOOL subprocess(char *const argv[], str_handle_lines_t linehandler, void *data);
+char *l_to_a(long N, int base);
+int load_licence(unsigned char **data);
+void save_licence(unsigned char *data, int length);
+void rd_create_ui(void);
+RD_BOOL rd_pstcache_mkdir(void);
+int rd_open_file(char *filename);
+void rd_close_file(int fd);
+int rd_read_file(int fd, void *ptr, int len);
+int rd_write_file(int fd, void *ptr, int len);
+int rd_lseek_file(int fd, int offset);
+RD_BOOL rd_lock_file(int fd, int start, int len);
+/* rdp5.c */
+void rdp5_process(STREAM s);
+/* rdp.c */
+void rdp_out_unistr(STREAM s, char *string, int len);
+void rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size);
+void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1,
+		    uint16 param2);
+void rdp_send_client_window_status(int status);
+void process_colour_pointer_pdu(STREAM s);
+void process_new_pointer_pdu(STREAM s);
+void process_cached_pointer_pdu(STREAM s);
+void process_system_pointer_pdu(STREAM s);
+void process_bitmap_updates(STREAM s);
+void process_palette(STREAM s);
+void process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason);
+void rdp_main_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason);
+RD_BOOL rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason);
+RD_BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, char *command,
+		    char *directory, RD_BOOL reconnect);
+void rdp_reset_state(void);
+void rdp_disconnect(void);
+/* rdpdr.c */
+int get_device_index(RD_NTHANDLE handle);
+void convert_to_unix_filename(char *filename);
+void rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,
+			   uint32 length);
+RD_BOOL rdpdr_init();
+void rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, RD_BOOL * timeout);
+struct async_iorequest *rdpdr_remove_iorequest(struct async_iorequest *prev,
+					       struct async_iorequest *iorq);
+void rdpdr_check_fds(fd_set * rfds, fd_set * wfds, RD_BOOL timed_out);
+RD_BOOL rdpdr_abort_io(uint32 fd, uint32 major, RD_NTSTATUS status);
+/* rdpsnd.c */
+void rdpsnd_record(const void *data, unsigned int size);
+RD_BOOL rdpsnd_init(char *optarg);
+void rdpsnd_show_help(void);
+void rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv);
+void rdpsnd_check_fds(fd_set * rfds, fd_set * wfds);
+struct audio_packet *rdpsnd_queue_current_packet(void);
+RD_BOOL rdpsnd_queue_empty(void);
+void rdpsnd_queue_next(unsigned long completed_in_us);
+int rdpsnd_queue_next_tick(void);
+void rdpsnd_reset_state(void);
+/* secure.c */
+void sec_hash_to_string(char *out, int out_size, uint8 * in, int in_size);
+void sec_hash_sha1_16(uint8 * out, uint8 * in, uint8 * salt1);
+void sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt);
+void sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2);
+void buf_out_uint32(uint8 * buffer, uint32 value);
+void sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data,
+	      int datalen);
+void sec_decrypt(uint8 * data, int length);
+STREAM sec_init(uint32 flags, int maxlen);
+void sec_send_to_channel(STREAM s, uint32 flags, uint16 channel);
+void sec_send(STREAM s, uint32 flags);
+void sec_process_mcs_data(STREAM s);
+STREAM sec_recv(uint8 * rdpver);
+RD_BOOL sec_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect);
+void sec_disconnect(void);
+void sec_reset_state(void);
+/* serial.c */
+int serial_enum_devices(uint32 * id, char *optarg);
+RD_BOOL serial_get_event(RD_NTHANDLE handle, uint32 * result);
+RD_BOOL serial_get_timeout(RD_NTHANDLE handle, uint32 length, uint32 * timeout,
+			   uint32 * itv_timeout);
+/* tcp.c */
+STREAM tcp_init(uint32 maxlen);
+void tcp_send(STREAM s);
+STREAM tcp_recv(STREAM s, uint32 length);
+RD_BOOL tcp_connect(char *server);
+void tcp_disconnect(void);
+char *tcp_get_address(void);
+RD_BOOL tcp_is_connected(void);
+void tcp_reset_state(void);
+RD_BOOL tcp_tls_connect(void);
+RD_BOOL tcp_tls_get_server_pubkey(STREAM s);
+void tcp_run_ui(RD_BOOL run);
+
+/* asn.c */
+RD_BOOL ber_in_header(STREAM s, int *tagval, int *length);
+void ber_out_header(STREAM s, int tagval, int length);
+RD_BOOL ber_parse_header(STREAM s, int tagval, int *length);
+void ber_out_integer(STREAM s, int value);
+
+/* xclip.c */
+void ui_clip_format_announce(uint8 * data, uint32 length);
+void ui_clip_handle_data(uint8 * data, uint32 length);
+void ui_clip_request_failed(void);
+void ui_clip_request_data(uint32 format);
+void ui_clip_sync(void);
+void ui_clip_set_mode(const char *optarg);
+void xclip_init(void);
+void xclip_deinit(void);
+/* xkeymap.c */
+RD_BOOL xkeymap_from_locale(const char *locale);
+FILE *xkeymap_open(const char *filename);
+void xkeymap_init(void);
+RD_BOOL handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, RD_BOOL pressed);
+key_translation xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state);
+void xkeymap_send_keys(uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time,
+		       RD_BOOL pressed, uint8 nesting);
+uint16 xkeymap_translate_button(unsigned int button);
+char *get_ksname(uint32 keysym);
+void save_remote_modifiers(uint8 scancode);
+void restore_remote_modifiers(uint32 ev_time, uint8 scancode);
+void ensure_remote_modifiers(uint32 ev_time, key_translation tr);
+unsigned int read_keyboard_state(void);
+uint16 ui_get_numlock_state(unsigned int state);
+void reset_modifier_keys(void);
+void rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode);
+/* xwin.c */
+RD_BOOL get_key_state(unsigned int state, uint32 keysym);
+RD_BOOL ui_init(void);
+void ui_init_connection(void);
+void ui_deinit(void);
+RD_BOOL ui_create_window(void);
+void ui_resize_window(void);
+void ui_destroy_window(void);
+RD_BOOL ui_have_window(void);
+void xwin_toggle_fullscreen(void);
+int ui_select(int rdp_socket);
+void ui_move_pointer(int x, int y);
+RD_HBITMAP ui_create_bitmap(int width, int height, uint8 * data);
+void ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data);
+void ui_destroy_bitmap(RD_HBITMAP bmp);
+RD_HGLYPH ui_create_glyph(int width, int height, uint8 * data);
+void ui_destroy_glyph(RD_HGLYPH glyph);
+RD_HCURSOR ui_create_cursor(unsigned int x, unsigned int y, int width, int height, uint8 * andmask,
+			    uint8 * xormask, int bpp);
+void ui_set_cursor(RD_HCURSOR cursor);
+void ui_destroy_cursor(RD_HCURSOR cursor);
+void ui_set_null_cursor(void);
+RD_HCOLOURMAP ui_create_colourmap(COLOURMAP * colours);
+void ui_destroy_colourmap(RD_HCOLOURMAP map);
+void ui_set_colourmap(RD_HCOLOURMAP map);
+void ui_set_clip(int x, int y, int cx, int cy);
+void ui_reset_clip(void);
+void ui_bell(void);
+void ui_destblt(uint8 opcode, int x, int y, int cx, int cy);
+void ui_patblt(uint8 opcode, int x, int y, int cx, int cy, BRUSH * brush, int bgcolour,
+	       int fgcolour);
+void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy, int srcx, int srcy);
+void ui_memblt(uint8 opcode, int x, int y, int cx, int cy, RD_HBITMAP src, int srcx, int srcy);
+void ui_triblt(uint8 opcode, int x, int y, int cx, int cy, RD_HBITMAP src, int srcx, int srcy,
+	       BRUSH * brush, int bgcolour, int fgcolour);
+void ui_line(uint8 opcode, int startx, int starty, int endx, int endy, PEN * pen);
+void ui_rect(int x, int y, int cx, int cy, int colour);
+void ui_polygon(uint8 opcode, uint8 fillmode, RD_POINT * point, int npoints, BRUSH * brush,
+		int bgcolour, int fgcolour);
+void ui_polyline(uint8 opcode, RD_POINT * points, int npoints, PEN * pen);
+void ui_ellipse(uint8 opcode, uint8 fillmode, int x, int y, int cx, int cy, BRUSH * brush,
+		int bgcolour, int fgcolour);
+void ui_draw_glyph(int mixmode, int x, int y, int cx, int cy, RD_HGLYPH glyph, int srcx, int srcy,
+		   int bgcolour, int fgcolour);
+void ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y, int clipx,
+		  int clipy, int clipcx, int clipcy, int boxx, int boxy, int boxcx, int boxcy,
+		  BRUSH * brush, int bgcolour, int fgcolour, uint8 * text, uint8 length);
+void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy);
+void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy);
+void ui_begin_update(void);
+void ui_end_update(void);
+void ui_seamless_begin(RD_BOOL hidden);
+void ui_seamless_end();
+void ui_seamless_hide_desktop(void);
+void ui_seamless_unhide_desktop(void);
+void ui_seamless_toggle(void);
+void ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent,
+			       unsigned long flags);
+void ui_seamless_destroy_window(unsigned long id, unsigned long flags);
+void ui_seamless_destroy_group(unsigned long id, unsigned long flags);
+void ui_seamless_seticon(unsigned long id, const char *format, int width, int height, int chunk,
+			 const char *data, int chunk_len);
+void ui_seamless_delicon(unsigned long id, const char *format, int width, int height);
+void ui_seamless_move_window(unsigned long id, int x, int y, int width, int height,
+			     unsigned long flags);
+void ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags);
+void ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags);
+void ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags);
+void ui_seamless_syncbegin(unsigned long flags);
+void ui_seamless_ack(unsigned int serial);
+/* lspci.c */
+RD_BOOL lspci_init(void);
+/* seamless.c */
+RD_BOOL seamless_init(void);
+void seamless_reset_state(void);
+unsigned int seamless_send_sync(void);
+unsigned int seamless_send_state(unsigned long id, unsigned int state, unsigned long flags);
+unsigned int seamless_send_position(unsigned long id, int x, int y, int width, int height,
+				    unsigned long flags);
+void seamless_select_timeout(struct timeval *tv);
+unsigned int seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags);
+unsigned int seamless_send_focus(unsigned long id, unsigned long flags);
+unsigned int seamless_send_destroy(unsigned long id);
+unsigned int seamless_send_spawn(char *cmd);
+unsigned int seamless_send_persistent(RD_BOOL);
+
+/* scard.c */
+void scard_lock(int lock);
+void scard_unlock(int lock);
+int scard_enum_devices(uint32 * id, char *optarg);
+void scardSetInfo(uint32 epoch, uint32 device, uint32 id, uint32 bytes_out);
+void scard_reset_state();
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+}
+#endif
+/* *INDENT-ON* */
+
+#endif
Index: /trunk/src/VBox/RDP/client-1.8.3/proto.head
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/proto.head	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/proto.head	(revision 55121)
@@ -0,0 +1,26 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Copyright (C) Matthew Chapman 1999-2007
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef RDESKTOP_PROTO_H
+#define RDESKTOP_PROTO_H
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* *INDENT-ON* */
Index: /trunk/src/VBox/RDP/client-1.8.3/proto.tail
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/proto.tail	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/proto.tail	(revision 55121)
@@ -0,0 +1,8 @@
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+}
+#endif
+/* *INDENT-ON* */
+
+#endif
Index: /trunk/src/VBox/RDP/client-1.8.3/pstcache.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/pstcache.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/pstcache.c	(revision 55121)
@@ -0,0 +1,199 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Persistent Bitmap Cache routines
+   Copyright (C) Jeroen Meijer <jeroen@oldambt7.com> 2004-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+
+#define MAX_CELL_SIZE		0x1000	/* pixels */
+
+#define IS_PERSISTENT(id) (id < 8 && g_pstcache_fd[id] > 0)
+
+extern int g_server_depth;
+extern RD_BOOL g_bitmap_cache;
+extern RD_BOOL g_bitmap_cache_persist_enable;
+extern RD_BOOL g_bitmap_cache_precache;
+
+int g_pstcache_fd[8];
+int g_pstcache_Bpp;
+RD_BOOL g_pstcache_enumerated = False;
+uint8 zero_key[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+
+/* Update mru stamp/index for a bitmap */
+void
+pstcache_touch_bitmap(uint8 cache_id, uint16 cache_idx, uint32 stamp)
+{
+	int fd;
+
+	if (!IS_PERSISTENT(cache_id) || cache_idx >= BMPCACHE2_NUM_PSTCELLS)
+		return;
+
+	fd = g_pstcache_fd[cache_id];
+	rd_lseek_file(fd, 12 + cache_idx * (g_pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
+	rd_write_file(fd, &stamp, sizeof(stamp));
+}
+
+/* Load a bitmap from the persistent cache */
+RD_BOOL
+pstcache_load_bitmap(uint8 cache_id, uint16 cache_idx)
+{
+	uint8 *celldata;
+	int fd;
+	CELLHEADER cellhdr;
+	RD_HBITMAP bitmap;
+
+	if (!g_bitmap_cache_persist_enable)
+		return False;
+
+	if (!IS_PERSISTENT(cache_id) || cache_idx >= BMPCACHE2_NUM_PSTCELLS)
+		return False;
+
+	fd = g_pstcache_fd[cache_id];
+	rd_lseek_file(fd, cache_idx * (g_pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
+	rd_read_file(fd, &cellhdr, sizeof(CELLHEADER));
+	celldata = (uint8 *) xmalloc(cellhdr.length);
+	rd_read_file(fd, celldata, cellhdr.length);
+
+	bitmap = ui_create_bitmap(cellhdr.width, cellhdr.height, celldata);
+	DEBUG(("Load bitmap from disk: id=%d, idx=%d, bmp=%p)\n", cache_id, cache_idx, bitmap));
+	cache_put_bitmap(cache_id, cache_idx, bitmap);
+
+	xfree(celldata);
+	return True;
+}
+
+/* Store a bitmap in the persistent cache */
+RD_BOOL
+pstcache_save_bitmap(uint8 cache_id, uint16 cache_idx, uint8 * key,
+		     uint8 width, uint8 height, uint16 length, uint8 * data)
+{
+	int fd;
+	CELLHEADER cellhdr;
+
+	if (!IS_PERSISTENT(cache_id) || cache_idx >= BMPCACHE2_NUM_PSTCELLS)
+		return False;
+
+	memcpy(cellhdr.key, key, sizeof(HASH_KEY));
+	cellhdr.width = width;
+	cellhdr.height = height;
+	cellhdr.length = length;
+	cellhdr.stamp = 0;
+
+	fd = g_pstcache_fd[cache_id];
+	rd_lseek_file(fd, cache_idx * (g_pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
+	rd_write_file(fd, &cellhdr, sizeof(CELLHEADER));
+	rd_write_file(fd, data, length);
+
+	return True;
+}
+
+/* List the bitmap keys from the persistent cache file */
+int
+pstcache_enumerate(uint8 id, HASH_KEY * keylist)
+{
+	int fd, n;
+	uint16 idx;
+	sint16 mru_idx[0xa00];
+	uint32 mru_stamp[0xa00];
+	CELLHEADER cellhdr;
+
+	if (!(g_bitmap_cache && g_bitmap_cache_persist_enable && IS_PERSISTENT(id)))
+		return 0;
+
+	/* The server disconnects if the bitmap cache content is sent more than once */
+	if (g_pstcache_enumerated)
+		return 0;
+
+	DEBUG_RDP5(("Persistent bitmap cache enumeration... "));
+	for (idx = 0; idx < BMPCACHE2_NUM_PSTCELLS; idx++)
+	{
+		fd = g_pstcache_fd[id];
+		rd_lseek_file(fd, idx * (g_pstcache_Bpp * MAX_CELL_SIZE + sizeof(CELLHEADER)));
+		if (rd_read_file(fd, &cellhdr, sizeof(CELLHEADER)) <= 0)
+			break;
+
+		if (memcmp(cellhdr.key, zero_key, sizeof(HASH_KEY)) != 0)
+		{
+			memcpy(keylist[idx], cellhdr.key, sizeof(HASH_KEY));
+
+			/* Pre-cache (not possible for 8 bit colour depth cause it needs a colourmap) */
+			if (g_bitmap_cache_precache && cellhdr.stamp && g_server_depth > 8)
+				pstcache_load_bitmap(id, idx);
+
+			/* Sort by stamp */
+			for (n = idx; n > 0 && cellhdr.stamp < mru_stamp[n - 1]; n--)
+			{
+				mru_idx[n] = mru_idx[n - 1];
+				mru_stamp[n] = mru_stamp[n - 1];
+			}
+
+			mru_idx[n] = idx;
+			mru_stamp[n] = cellhdr.stamp;
+		}
+		else
+		{
+			break;
+		}
+	}
+
+	DEBUG_RDP5(("%d cached bitmaps.\n", idx));
+
+	cache_rebuild_bmpcache_linked_list(id, mru_idx, idx);
+	g_pstcache_enumerated = True;
+	return idx;
+}
+
+/* initialise the persistent bitmap cache */
+RD_BOOL
+pstcache_init(uint8 cache_id)
+{
+	int fd;
+	char filename[256];
+
+	if (g_pstcache_enumerated)
+		return True;
+
+	g_pstcache_fd[cache_id] = 0;
+
+	if (!(g_bitmap_cache && g_bitmap_cache_persist_enable))
+		return False;
+
+	if (!rd_pstcache_mkdir())
+	{
+		DEBUG(("failed to get/make cache directory!\n"));
+		return False;
+	}
+
+	g_pstcache_Bpp = (g_server_depth + 7) / 8;
+	sprintf(filename, "cache/pstcache_%d_%d", cache_id, g_pstcache_Bpp);
+	DEBUG(("persistent bitmap cache file: %s\n", filename));
+
+	fd = rd_open_file(filename);
+	if (fd == -1)
+		return False;
+
+	if (!rd_lock_file(fd, 0, 0))
+	{
+		warning("Persistent bitmap caching is disabled. (The file is already in use)\n");
+		rd_close_file(fd);
+		return False;
+	}
+
+	g_pstcache_fd[cache_id] = fd;
+	return True;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/rdesktop.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdesktop.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdesktop.c	(revision 55121)
@@ -0,0 +1,1874 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Entrypoint and utility functions
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright 2002-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+   Copyright 2010-2014 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdarg.h>		/* va_list va_start va_end */
+#include <unistd.h>		/* read close getuid getgid getpid getppid gethostname */
+#include <fcntl.h>		/* open */
+#include <pwd.h>		/* getpwuid */
+#include <termios.h>		/* tcgetattr tcsetattr */
+#include <sys/stat.h>		/* stat */
+#include <sys/time.h>		/* gettimeofday */
+#include <sys/times.h>		/* times */
+#include <ctype.h>		/* toupper */
+#include <limits.h>
+#include <errno.h>
+#include <signal.h>
+#include "rdesktop.h"
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#ifdef HAVE_ICONV
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+#endif
+
+#ifdef EGD_SOCKET
+#include <sys/types.h>
+#include <sys/socket.h>		/* socket connect */
+#include <sys/un.h>		/* sockaddr_un */
+#endif
+
+#include "ssl.h"
+
+/* Reconnect timeout based on approxiamted cookie life-time */
+#define RECONNECT_TIMEOUT (3600+600)
+#define RDESKTOP_LICENSE_STORE "/.local/share/rdesktop/licenses"
+
+uint8 g_static_rdesktop_salt_16[16] = {
+	0xb8, 0x82, 0x29, 0x31, 0xc5, 0x39, 0xd9, 0x44,
+	0x54, 0x15, 0x5e, 0x14, 0x71, 0x38, 0xd5, 0x4d
+};
+
+char g_title[64] = "";
+char *g_username;
+char g_password[64] = "";
+char g_hostname[16] = "";
+char g_keymapname[PATH_MAX] = "";
+unsigned int g_keylayout = 0x409;	/* Defaults to US keyboard layout */
+int g_keyboard_type = 0x4;	/* Defaults to US keyboard layout */
+int g_keyboard_subtype = 0x0;	/* Defaults to US keyboard layout */
+int g_keyboard_functionkeys = 0xc;	/* Defaults to US keyboard layout */
+int g_sizeopt = 0;		/* If non-zero, a special size has been
+				   requested. If 1, the geometry will be fetched
+				   from _NET_WORKAREA. If negative, absolute value
+				   specifies the percent of the whole screen. */
+int g_width = 800;
+int g_height = 600;
+int g_xpos = 0;
+int g_ypos = 0;
+int g_pos = 0;			/* 0 position unspecified,
+				   1 specified,
+				   2 xpos neg,
+				   4 ypos neg  */
+extern int g_tcp_port_rdp;
+int g_server_depth = -1;
+int g_win_button_size = 0;	/* If zero, disable single app mode */
+RD_BOOL g_network_error = False;
+RD_BOOL g_bitmap_compression = True;
+RD_BOOL g_sendmotion = True;
+RD_BOOL g_bitmap_cache = True;
+RD_BOOL g_bitmap_cache_persist_enable = False;
+RD_BOOL g_bitmap_cache_precache = True;
+RD_BOOL g_use_ctrl = True;
+RD_BOOL g_encryption = True;
+RD_BOOL g_encryption_initial = True;
+RD_BOOL g_packet_encryption = True;
+RD_BOOL g_desktop_save = True;	/* desktop save order */
+RD_BOOL g_polygon_ellipse_orders = True;	/* polygon / ellipse orders */
+RD_BOOL g_fullscreen = False;
+RD_BOOL g_grab_keyboard = True;
+RD_BOOL g_hide_decorations = False;
+RDP_VERSION g_rdp_version = RDP_V5;	/* Default to version 5 */
+RD_BOOL g_rdpclip = True;
+RD_BOOL g_console_session = False;
+RD_BOOL g_numlock_sync = False;
+RD_BOOL g_lspci_enabled = False;
+RD_BOOL g_owncolmap = False;
+RD_BOOL g_ownbackstore = True;	/* We can't rely on external BackingStore */
+RD_BOOL g_seamless_rdp = False;
+RD_BOOL g_use_password_as_pin = False;
+char g_seamless_shell[512];
+char g_seamless_spawn_cmd[512];
+RD_BOOL g_seamless_persistent_mode = True;
+RD_BOOL g_user_quit = False;
+uint32 g_embed_wnd;
+uint32 g_rdp5_performanceflags =
+	RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS | RDP5_NO_CURSOR_SHADOW;
+/* Session Directory redirection */
+RD_BOOL g_redirect = False;
+char *g_redirect_server;
+uint32 g_redirect_server_len;
+char *g_redirect_domain;
+uint32 g_redirect_domain_len;
+char *g_redirect_username;
+uint32 g_redirect_username_len;
+uint8 *g_redirect_lb_info;
+uint32 g_redirect_lb_info_len;
+uint8 *g_redirect_cookie;
+uint32 g_redirect_cookie_len;
+uint32 g_redirect_flags = 0;
+uint32 g_redirect_session_id = 0;
+
+uint32 g_reconnect_logonid = 0;
+char g_reconnect_random[16];
+time_t g_reconnect_random_ts;
+RD_BOOL g_has_reconnect_random = False;
+RD_BOOL g_reconnect_loop = False;
+uint8 g_client_random[SEC_RANDOM_SIZE];
+RD_BOOL g_pending_resize = False;
+
+#ifdef WITH_RDPSND
+RD_BOOL g_rdpsnd = False;
+#endif
+
+#ifdef HAVE_ICONV
+char g_codepage[16] = "";
+#endif
+
+char *g_sc_csp_name = NULL;	/* Smartcard CSP name  */
+char *g_sc_reader_name = NULL;
+char *g_sc_card_name = NULL;
+char *g_sc_container_name = NULL;
+
+extern RDPDR_DEVICE g_rdpdr_device[];
+extern uint32 g_num_devices;
+extern char *g_rdpdr_clientname;
+
+#ifdef RDP2VNC
+extern int rfb_port;
+extern int defer_time;
+void
+rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
+		char *shell, char *directory);
+#endif
+/* Display usage information */
+static void
+usage(char *program)
+{
+	fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
+	fprintf(stderr,
+		"Version " PACKAGE_VERSION ". Copyright (C) 1999-2011 Matthew Chapman et al.\n");
+	fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
+
+	fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
+#ifdef RDP2VNC
+	fprintf(stderr, "   -V: vnc port\n");
+	fprintf(stderr, "   -Q: defer time (ms)\n");
+#endif
+	fprintf(stderr, "   -u: user name\n");
+	fprintf(stderr, "   -d: domain\n");
+	fprintf(stderr, "   -s: shell / seamless application to start remotly\n");
+	fprintf(stderr, "   -c: working directory\n");
+	fprintf(stderr, "   -p: password (- to prompt)\n");
+	fprintf(stderr, "   -n: client hostname\n");
+	fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
+	fprintf(stderr, "   -g: desktop geometry (WxH)\n");
+#ifdef WITH_SCARD
+	fprintf(stderr, "   -i: enables smartcard authentication, password is used as pin\n");
+#endif
+	fprintf(stderr, "   -f: full-screen mode\n");
+	fprintf(stderr, "   -b: force bitmap updates\n");
+#ifdef HAVE_ICONV
+	fprintf(stderr, "   -L: local codepage\n");
+#endif
+	fprintf(stderr, "   -A: path to SeamlessRDP shell, this enables SeamlessRDP mode\n");
+	fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");
+	fprintf(stderr, "   -e: disable encryption (French TS)\n");
+	fprintf(stderr, "   -E: disable encryption from client to server\n");
+	fprintf(stderr, "   -m: do not send motion events\n");
+	fprintf(stderr, "   -C: use private colour map\n");
+	fprintf(stderr, "   -D: hide window manager decorations\n");
+	fprintf(stderr, "   -K: keep window manager key bindings\n");
+	fprintf(stderr, "   -S: caption button size (single application mode)\n");
+	fprintf(stderr, "   -T: window title\n");
+	fprintf(stderr, "   -t: disable use of remote ctrl\n");
+	fprintf(stderr, "   -N: enable numlock syncronization\n");
+	fprintf(stderr, "   -X: embed into another window with a given id.\n");
+	fprintf(stderr, "   -a: connection colour depth\n");
+	fprintf(stderr, "   -z: enable rdp compression\n");
+	fprintf(stderr, "   -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex nr.)\n");
+	fprintf(stderr, "   -P: use persistent bitmap caching\n");
+	fprintf(stderr, "   -r: enable specified device redirection (this flag can be repeated)\n");
+	fprintf(stderr,
+		"         '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n");
+	fprintf(stderr, "             or      COM1=/dev/ttyS0,COM2=/dev/ttyS1\n");
+	fprintf(stderr,
+		"         '-r disk:floppy=/mnt/floppy': enable redirection of /mnt/floppy to 'floppy' share\n");
+	fprintf(stderr, "             or   'floppy=/mnt/floppy,cdrom=/mnt/cdrom'\n");
+	fprintf(stderr, "         '-r clientname=<client name>': Set the client name displayed\n");
+	fprintf(stderr, "             for redirected disks\n");
+	fprintf(stderr,
+		"         '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1\n");
+	fprintf(stderr, "             or      LPT1=/dev/lp0,LPT2=/dev/lp1\n");
+	fprintf(stderr, "         '-r printer:mydeskjet': enable printer redirection\n");
+	fprintf(stderr,
+		"             or      mydeskjet=\"HP LaserJet IIIP\" to enter server driver as well\n");
+#ifdef WITH_RDPSND
+	fprintf(stderr,
+		"         '-r sound:[local[:driver[:device]]|off|remote]': enable sound redirection\n");
+	fprintf(stderr, "                     remote would leave sound on server\n");
+	fprintf(stderr, "                     available drivers for 'local':\n");
+	rdpsnd_show_help();
+#endif
+	fprintf(stderr,
+		"         '-r clipboard:[off|PRIMARYCLIPBOARD|CLIPBOARD]': enable clipboard\n");
+	fprintf(stderr, "                      redirection.\n");
+	fprintf(stderr,
+		"                      'PRIMARYCLIPBOARD' looks at both PRIMARY and CLIPBOARD\n");
+	fprintf(stderr, "                      when sending data to server.\n");
+	fprintf(stderr, "                      'CLIPBOARD' looks at only CLIPBOARD.\n");
+#ifdef WITH_SCARD
+	fprintf(stderr, "         '-r scard[:\"Scard Name\"=\"Alias Name[;Vendor Name]\"[,...]]\n");
+	fprintf(stderr, "          example: -r scard:\"eToken PRO 00 00\"=\"AKS ifdh 0\"\n");
+	fprintf(stderr,
+		"                   \"eToken PRO 00 00\" -> Device in Linux/Unix enviroment\n");
+	fprintf(stderr,
+		"                   \"AKS ifdh 0\"       -> Device shown in Windows enviroment \n");
+	fprintf(stderr, "          example: -r scard:\"eToken PRO 00 00\"=\"AKS ifdh 0;AKS\"\n");
+	fprintf(stderr,
+		"                   \"eToken PRO 00 00\" -> Device in Linux/Unix enviroment\n");
+	fprintf(stderr,
+		"                   \"AKS ifdh 0\"       -> Device shown in Windows enviroment \n");
+	fprintf(stderr,
+		"                   \"AKS\"              -> Device vendor name                 \n");
+#endif
+	fprintf(stderr, "   -0: attach to console\n");
+	fprintf(stderr, "   -4: use RDP version 4\n");
+	fprintf(stderr, "   -5: use RDP version 5 (default)\n");
+#ifdef WITH_SCARD
+	fprintf(stderr, "   -o: name=value: Adds an additional option to rdesktop.\n");
+	fprintf(stderr,
+		"           sc-csp-name        Specifies the Crypto Service Provider name which\n");
+	fprintf(stderr,
+		"                              is used to authenticate the user by smartcard\n");
+	fprintf(stderr,
+		"           sc-container-name  Specifies the container name, this is usally the username\n");
+	fprintf(stderr, "           sc-reader-name     Smartcard reader name to use\n");
+	fprintf(stderr,
+		"           sc-card-name       Specifies the card name of the smartcard to use\n");
+#endif
+
+	fprintf(stderr, "\n");
+
+}
+
+static int
+handle_disconnect_reason(RD_BOOL deactivated, uint16 reason)
+{
+	char *text;
+	int retval;
+
+	switch (reason)
+	{
+		case exDiscReasonNoInfo:
+			text = "No information available";
+			if (deactivated)
+				retval = EX_OK;
+			else
+				retval = EXRD_UNKNOWN;
+			break;
+
+		case exDiscReasonAPIInitiatedDisconnect:
+			text = "Server initiated disconnect";
+			retval = EXRD_API_DISCONNECT;
+			break;
+
+		case exDiscReasonAPIInitiatedLogoff:
+			text = "Server initiated logoff";
+			retval = EXRD_API_LOGOFF;
+			break;
+
+		case exDiscReasonServerIdleTimeout:
+			text = "Server idle timeout reached";
+			retval = EXRD_IDLE_TIMEOUT;
+			break;
+
+		case exDiscReasonServerLogonTimeout:
+			text = "Server logon timeout reached";
+			retval = EXRD_LOGON_TIMEOUT;
+			break;
+
+		case exDiscReasonReplacedByOtherConnection:
+			text = "The session was replaced";
+			retval = EXRD_REPLACED;
+			break;
+
+		case exDiscReasonOutOfMemory:
+			text = "The server is out of memory";
+			retval = EXRD_OUT_OF_MEM;
+			break;
+
+		case exDiscReasonServerDeniedConnection:
+			text = "The server denied the connection";
+			retval = EXRD_DENIED;
+			break;
+
+		case exDiscReasonServerDeniedConnectionFips:
+			text = "The server denied the connection for security reason";
+			retval = EXRD_DENIED_FIPS;
+			break;
+
+		case exDiscReasonServerInsufficientPrivileges:
+			text = "The user cannot connect to the server due to insufficient access privileges.";
+			retval = EXRD_INSUFFICIENT_PRIVILEGES;
+			break;
+
+		case exDiscReasonServerFreshCredentialsRequired:
+			text = "The server does not accept saved user credentials and requires that the user enter their credentials for each connection.";
+			retval = EXRD_FRESH_CREDENTIALS_REQUIRED;
+			break;
+
+		case exDiscReasonRPCInitiatedDisconnectByUser:
+			text = "Disconnect initiated by administration tool";
+			retval = EXRD_RPC_DISCONNECT_BY_USER;
+			break;
+
+		case exDiscReasonByUser:
+			text = "Disconnect initiated by user";
+			retval = EXRD_DISCONNECT_BY_USER;
+			break;
+
+		case exDiscReasonLicenseInternal:
+			text = "Internal licensing error";
+			retval = EXRD_LIC_INTERNAL;
+			break;
+
+		case exDiscReasonLicenseNoLicenseServer:
+			text = "No license server available";
+			retval = EXRD_LIC_NOSERVER;
+			break;
+
+		case exDiscReasonLicenseNoLicense:
+			text = "No valid license available";
+			retval = EXRD_LIC_NOLICENSE;
+			break;
+
+		case exDiscReasonLicenseErrClientMsg:
+			text = "Invalid licensing message";
+			retval = EXRD_LIC_MSG;
+			break;
+
+		case exDiscReasonLicenseHwidDoesntMatchLicense:
+			text = "Hardware id doesn't match software license";
+			retval = EXRD_LIC_HWID;
+			break;
+
+		case exDiscReasonLicenseErrClientLicense:
+			text = "Client license error";
+			retval = EXRD_LIC_CLIENT;
+			break;
+
+		case exDiscReasonLicenseCantFinishProtocol:
+			text = "Network error during licensing protocol";
+			retval = EXRD_LIC_NET;
+			break;
+
+		case exDiscReasonLicenseClientEndedProtocol:
+			text = "Licensing protocol was not completed";
+			retval = EXRD_LIC_PROTO;
+			break;
+
+		case exDiscReasonLicenseErrClientEncryption:
+			text = "Incorrect client license encryption";
+			retval = EXRD_LIC_ENC;
+			break;
+
+		case exDiscReasonLicenseCantUpgradeLicense:
+			text = "Can't upgrade license";
+			retval = EXRD_LIC_UPGRADE;
+			break;
+
+		case exDiscReasonLicenseNoRemoteConnections:
+			text = "The server is not licensed to accept remote connections";
+			retval = EXRD_LIC_NOREMOTE;
+			break;
+
+		default:
+			if (reason > 0x1000 && reason < 0x7fff)
+			{
+				text = "Internal protocol error";
+			}
+			else
+			{
+				text = "Unknown reason";
+			}
+			retval = EXRD_UNKNOWN;
+	}
+	if (reason != exDiscReasonNoInfo)
+		fprintf(stderr, "disconnect: %s.\n", text);
+
+	return retval;
+}
+
+static void
+rdesktop_reset_state(void)
+{
+	rdp_reset_state();
+#ifdef WITH_SCARD
+	scard_reset_state();
+#endif
+#ifdef WITH_RDPSND
+	rdpsnd_reset_state();
+#endif
+}
+
+static RD_BOOL
+read_password(char *password, int size)
+{
+	struct termios tios;
+	RD_BOOL ret = False;
+	int istty = 0;
+	char *p;
+
+	if (tcgetattr(STDIN_FILENO, &tios) == 0)
+	{
+		fprintf(stderr, "Password: ");
+		tios.c_lflag &= ~ECHO;
+		tcsetattr(STDIN_FILENO, TCSANOW, &tios);
+		istty = 1;
+	}
+
+	if (fgets(password, size, stdin) != NULL)
+	{
+		ret = True;
+
+		/* strip final newline */
+		p = strchr(password, '\n');
+		if (p != NULL)
+			*p = 0;
+	}
+
+	if (istty)
+	{
+		tios.c_lflag |= ECHO;
+		tcsetattr(STDIN_FILENO, TCSANOW, &tios);
+		fprintf(stderr, "\n");
+	}
+
+	return ret;
+}
+
+static void
+parse_server_and_port(char *server)
+{
+	char *p;
+#ifdef IPv6
+	int addr_colons;
+#endif
+
+#ifdef IPv6
+	p = server;
+	addr_colons = 0;
+	while (*p)
+		if (*p++ == ':')
+			addr_colons++;
+	if (addr_colons >= 2)
+	{
+		/* numeric IPv6 style address format - [1:2:3::4]:port */
+		p = strchr(server, ']');
+		if (*server == '[' && p != NULL)
+		{
+			if (*(p + 1) == ':' && *(p + 2) != '\0')
+				g_tcp_port_rdp = strtol(p + 2, NULL, 10);
+			/* remove the port number and brackets from the address */
+			*p = '\0';
+			strncpy(server, server + 1, strlen(server));
+		}
+	}
+	else
+	{
+		/* dns name or IPv4 style address format - server.example.com:port or 1.2.3.4:port */
+		p = strchr(server, ':');
+		if (p != NULL)
+		{
+			g_tcp_port_rdp = strtol(p + 1, NULL, 10);
+			*p = 0;
+		}
+	}
+#else /* no IPv6 support */
+	p = strchr(server, ':');
+	if (p != NULL)
+	{
+		g_tcp_port_rdp = strtol(p + 1, NULL, 10);
+		*p = 0;
+	}
+#endif /* IPv6 */
+
+}
+
+/* Client program */
+int
+main(int argc, char *argv[])
+{
+	char server[256];
+	char fullhostname[64];
+	char domain[256];
+	char shell[256];
+	char directory[256];
+	RD_BOOL prompt_password, deactivated;
+	struct passwd *pw;
+	uint32 flags, ext_disc_reason = 0;
+	char *p;
+	int c;
+	char *locale = NULL;
+	int username_option = 0;
+	RD_BOOL geometry_option = False;
+#ifdef WITH_RDPSND
+	char *rdpsnd_optarg = NULL;
+#endif
+
+#ifdef HAVE_LOCALE_H
+	/* Set locale according to environment */
+	locale = setlocale(LC_ALL, "");
+	if (locale)
+	{
+		locale = xstrdup(locale);
+	}
+
+#endif
+
+	/* Ignore SIGPIPE, since we are using popen() */
+	struct sigaction act;
+	memset(&act, 0, sizeof(act));
+	act.sa_handler = SIG_IGN;
+	sigemptyset(&act.sa_mask);
+	act.sa_flags = 0;
+	sigaction(SIGPIPE, &act, NULL);
+
+	/* setup default flags for TS_INFO_PACKET */
+	flags = RDP_INFO_MOUSE | RDP_INFO_DISABLECTRLALTDEL
+		| RDP_INFO_UNICODE | RDP_INFO_MAXIMIZESHELL | RDP_INFO_ENABLEWINDOWSKEY;
+
+	prompt_password = False;
+	g_seamless_spawn_cmd[0] = domain[0] = g_password[0] = shell[0] = directory[0] = 0;
+	g_embed_wnd = 0;
+
+	g_num_devices = 0;
+
+#ifdef RDP2VNC
+#define VNCOPT "V:Q:"
+#else
+#define VNCOPT
+#endif
+	while ((c = getopt(argc, argv,
+			   VNCOPT "A:u:L:d:s:c:p:n:k:g:o:fbBeEitmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
+	{
+		switch (c)
+		{
+#ifdef RDP2VNC
+			case 'V':
+				rfb_port = strtol(optarg, NULL, 10);
+				if (rfb_port < 100)
+					rfb_port += 5900;
+				break;
+
+			case 'Q':
+				defer_time = strtol(optarg, NULL, 10);
+				if (defer_time < 0)
+					defer_time = 0;
+				break;
+#endif
+
+			case 'A':
+				g_seamless_rdp = True;
+				STRNCPY(g_seamless_shell, optarg, sizeof(g_seamless_shell));
+				break;
+
+			case 'u':
+				g_username = (char *) xmalloc(strlen(optarg) + 1);
+				STRNCPY(g_username, optarg, strlen(optarg) + 1);
+				username_option = 1;
+				break;
+
+			case 'L':
+#ifdef HAVE_ICONV
+				STRNCPY(g_codepage, optarg, sizeof(g_codepage));
+#else
+				error("iconv support not available\n");
+#endif
+				break;
+
+			case 'd':
+				STRNCPY(domain, optarg, sizeof(domain));
+				break;
+
+			case 's':
+				STRNCPY(shell, optarg, sizeof(shell));
+				g_seamless_persistent_mode = False;
+				break;
+
+			case 'c':
+				STRNCPY(directory, optarg, sizeof(directory));
+				break;
+
+			case 'p':
+				if ((optarg[0] == '-') && (optarg[1] == 0))
+				{
+					prompt_password = True;
+					break;
+				}
+
+				STRNCPY(g_password, optarg, sizeof(g_password));
+				flags |= RDP_INFO_AUTOLOGON;
+
+				/* try to overwrite argument so it won't appear in ps */
+				p = optarg;
+				while (*p)
+					*(p++) = 'X';
+				break;
+#ifdef WITH_SCARD
+			case 'i':
+				flags |= RDP_INFO_PASSWORD_IS_SC_PIN;
+				g_use_password_as_pin = True;
+				break;
+#endif
+			case 't':
+				g_use_ctrl = False;
+				break;
+
+			case 'n':
+				STRNCPY(g_hostname, optarg, sizeof(g_hostname));
+				break;
+
+			case 'k':
+				STRNCPY(g_keymapname, optarg, sizeof(g_keymapname));
+				break;
+
+			case 'g':
+				geometry_option = True;
+				g_fullscreen = False;
+				if (!strcmp(optarg, "workarea"))
+				{
+					g_sizeopt = 1;
+					break;
+				}
+
+				g_width = strtol(optarg, &p, 10);
+				if (g_width <= 0)
+				{
+					error("invalid geometry\n");
+					return EX_USAGE;
+				}
+
+				if (*p == 'x')
+					g_height = strtol(p + 1, &p, 10);
+
+				if (g_height <= 0)
+				{
+					error("invalid geometry\n");
+					return EX_USAGE;
+				}
+
+				if (*p == '%')
+				{
+					g_sizeopt = -g_width;
+					g_width = 800;
+					p++;
+				}
+
+				if (*p == '+' || *p == '-')
+				{
+					g_pos |= (*p == '-') ? 2 : 1;
+					g_xpos = strtol(p, &p, 10);
+
+				}
+				if (*p == '+' || *p == '-')
+				{
+					g_pos |= (*p == '-') ? 4 : 1;
+					g_ypos = strtol(p, NULL, 10);
+				}
+
+				break;
+
+			case 'f':
+				g_fullscreen = True;
+				break;
+
+			case 'b':
+				g_bitmap_cache = False;
+				break;
+
+			case 'B':
+				g_ownbackstore = False;
+				break;
+
+			case 'e':
+				g_encryption_initial = g_encryption = False;
+				break;
+			case 'E':
+				g_packet_encryption = False;
+				break;
+			case 'm':
+				g_sendmotion = False;
+				break;
+
+			case 'C':
+				g_owncolmap = True;
+				break;
+
+			case 'D':
+				g_hide_decorations = True;
+				break;
+
+			case 'K':
+				g_grab_keyboard = False;
+				break;
+
+			case 'S':
+				if (!strcmp(optarg, "standard"))
+				{
+					g_win_button_size = 18;
+					break;
+				}
+
+				g_win_button_size = strtol(optarg, &p, 10);
+
+				if (*p)
+				{
+					error("invalid button size\n");
+					return EX_USAGE;
+				}
+
+				break;
+
+			case 'T':
+				STRNCPY(g_title, optarg, sizeof(g_title));
+				break;
+
+			case 'N':
+				g_numlock_sync = True;
+				break;
+
+			case 'X':
+				g_embed_wnd = strtol(optarg, NULL, 0);
+				break;
+
+			case 'a':
+				g_server_depth = strtol(optarg, NULL, 10);
+				if (g_server_depth != 8 &&
+				    g_server_depth != 16 &&
+				    g_server_depth != 15 && g_server_depth != 24
+				    && g_server_depth != 32)
+				{
+					error("Invalid server colour depth.\n");
+					return EX_USAGE;
+				}
+				break;
+
+			case 'z':
+				DEBUG(("rdp compression enabled\n"));
+				flags |= (RDP_INFO_COMPRESSION | RDP_INFO_COMPRESSION2);
+				break;
+
+			case 'x':
+				if (str_startswith(optarg, "m"))	/* modem */
+				{
+					g_rdp5_performanceflags = RDP5_NO_CURSOR_SHADOW |
+						RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
+						RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
+				}
+				else if (str_startswith(optarg, "b"))	/* broadband */
+				{
+					g_rdp5_performanceflags =
+						RDP5_NO_CURSOR_SHADOW | RDP5_NO_WALLPAPER;
+				}
+				else if (str_startswith(optarg, "l"))	/* lan */
+				{
+					g_rdp5_performanceflags =
+						RDP5_NO_CURSOR_SHADOW | RDP5_DISABLE_NOTHING;
+				}
+				else
+				{
+					g_rdp5_performanceflags =
+						RDP5_NO_CURSOR_SHADOW | strtol(optarg, NULL, 16);
+				}
+				break;
+
+			case 'P':
+				g_bitmap_cache_persist_enable = True;
+				break;
+
+			case 'r':
+
+				if (str_startswith(optarg, "sound"))
+				{
+					optarg += 5;
+
+					if (*optarg == ':')
+					{
+						optarg++;
+						while ((p = next_arg(optarg, ',')))
+						{
+							if (str_startswith(optarg, "remote"))
+								flags |= RDP_INFO_REMOTE_CONSOLE_AUDIO;
+
+							if (str_startswith(optarg, "local"))
+#ifdef WITH_RDPSND
+							{
+								rdpsnd_optarg =
+									next_arg(optarg, ':');
+								g_rdpsnd = True;
+							}
+
+#else
+								warning("Not compiled with sound support\n");
+#endif
+
+							if (str_startswith(optarg, "off"))
+#ifdef WITH_RDPSND
+								g_rdpsnd = False;
+#else
+								warning("Not compiled with sound support\n");
+#endif
+
+							optarg = p;
+						}
+					}
+					else
+					{
+#ifdef WITH_RDPSND
+						g_rdpsnd = True;
+#else
+						warning("Not compiled with sound support\n");
+#endif
+					}
+				}
+				else if (str_startswith(optarg, "disk"))
+				{
+					/* -r disk:h:=/mnt/floppy */
+					disk_enum_devices(&g_num_devices, optarg + 4);
+				}
+				else if (str_startswith(optarg, "comport"))
+				{
+					serial_enum_devices(&g_num_devices, optarg + 7);
+				}
+				else if (str_startswith(optarg, "lspci"))
+				{
+					g_lspci_enabled = True;
+				}
+				else if (str_startswith(optarg, "lptport"))
+				{
+					parallel_enum_devices(&g_num_devices, optarg + 7);
+				}
+				else if (str_startswith(optarg, "printer"))
+				{
+					printer_enum_devices(&g_num_devices, optarg + 7);
+				}
+				else if (str_startswith(optarg, "clientname"))
+				{
+					g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
+					strcpy(g_rdpdr_clientname, optarg + 11);
+				}
+				else if (str_startswith(optarg, "clipboard"))
+				{
+					optarg += 9;
+
+					if (*optarg == ':')
+					{
+						optarg++;
+
+						if (str_startswith(optarg, "off"))
+							g_rdpclip = False;
+						else
+							cliprdr_set_mode(optarg);
+					}
+					else
+						g_rdpclip = True;
+				}
+				else if (strncmp("scard", optarg, 5) == 0)
+				{
+#ifdef WITH_SCARD
+					scard_enum_devices(&g_num_devices, optarg + 5);
+#else
+					warning("Not compiled with smartcard support\n");
+#endif
+				}
+				else
+				{
+					warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard, scard\n");
+				}
+				break;
+
+			case '0':
+				g_console_session = True;
+				break;
+
+			case '4':
+				g_rdp_version = RDP_V4;
+				break;
+
+			case '5':
+				g_rdp_version = RDP_V5;
+				break;
+#if WITH_SCARD
+			case 'o':
+				{
+					char *p = strchr(optarg, '=');
+					if (p == NULL)
+					{
+						warning("Skipping option '%s' specified, lacks name=value format.\n");
+						continue;
+					}
+
+					if (strncmp(optarg, "sc-csp-name", strlen("sc-scp-name")) ==
+					    0)
+						g_sc_csp_name = strdup(p + 1);
+					else if (strncmp
+						 (optarg, "sc-reader-name",
+						  strlen("sc-reader-name")) == 0)
+						g_sc_reader_name = strdup(p + 1);
+					else if (strncmp
+						 (optarg, "sc-card-name",
+						  strlen("sc-card-name")) == 0)
+						g_sc_card_name = strdup(p + 1);
+					else if (strncmp
+						 (optarg, "sc-container-name",
+						  strlen("sc-container-name")) == 0)
+						g_sc_container_name = strdup(p + 1);
+
+				}
+				break;
+#endif
+			case 'h':
+			case '?':
+			default:
+				usage(argv[0]);
+				return EX_USAGE;
+		}
+	}
+
+	if (argc - optind != 1)
+	{
+		usage(argv[0]);
+		return EX_USAGE;
+	}
+
+	STRNCPY(server, argv[optind], sizeof(server));
+	parse_server_and_port(server);
+
+	if (g_seamless_rdp)
+	{
+		if (shell[0])
+			STRNCPY(g_seamless_spawn_cmd, shell, sizeof(g_seamless_spawn_cmd));
+
+		STRNCPY(shell, g_seamless_shell, sizeof(shell));
+
+		if (g_win_button_size)
+		{
+			error("You cannot use -S and -A at the same time\n");
+			return EX_USAGE;
+		}
+		g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG;
+		if (geometry_option)
+		{
+			error("You cannot use -g and -A at the same time\n");
+			return EX_USAGE;
+		}
+		if (g_fullscreen)
+		{
+			error("You cannot use -f and -A at the same time\n");
+			return EX_USAGE;
+		}
+		if (g_hide_decorations)
+		{
+			error("You cannot use -D and -A at the same time\n");
+			return EX_USAGE;
+		}
+		if (g_embed_wnd)
+		{
+			error("You cannot use -X and -A at the same time\n");
+			return EX_USAGE;
+		}
+		if (g_rdp_version < RDP_V5)
+		{
+			error("You cannot use -4 and -A at the same time\n");
+			return EX_USAGE;
+		}
+		g_sizeopt = -100;
+		g_grab_keyboard = False;
+	}
+
+	if (!username_option)
+	{
+		pw = getpwuid(getuid());
+		if ((pw == NULL) || (pw->pw_name == NULL))
+		{
+			error("could not determine username, use -u\n");
+			return EX_OSERR;
+		}
+		/* +1 for trailing \0 */
+		int pwlen = strlen(pw->pw_name) + 1;
+		g_username = (char *) xmalloc(pwlen);
+		STRNCPY(g_username, pw->pw_name, pwlen);
+	}
+
+#ifdef HAVE_ICONV
+	if (g_codepage[0] == 0)
+	{
+		if (setlocale(LC_CTYPE, ""))
+		{
+			STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
+		}
+		else
+		{
+			STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
+		}
+	}
+#endif
+
+	if (g_hostname[0] == 0)
+	{
+		if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
+		{
+			error("could not determine local hostname, use -n\n");
+			return EX_OSERR;
+		}
+
+		p = strchr(fullhostname, '.');
+		if (p != NULL)
+			*p = 0;
+
+		STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
+	}
+
+	if (g_keymapname[0] == 0)
+	{
+		if (locale && xkeymap_from_locale(locale))
+		{
+			fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname);
+		}
+		else
+		{
+			STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname));
+		}
+	}
+	if (locale)
+		xfree(locale);
+
+
+	if (prompt_password && read_password(g_password, sizeof(g_password)))
+		flags |= RDP_INFO_AUTOLOGON;
+
+	if (g_title[0] == 0)
+	{
+		strcpy(g_title, "rdesktop - ");
+		strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
+	}
+
+#ifdef RDP2VNC
+	rdp2vnc_connect(server, flags, domain, g_password, shell, directory);
+	return EX_OK;
+#else
+
+	/* Only startup ctrl functionality is seamless are used for now. */
+	if (g_use_ctrl && g_seamless_rdp)
+	{
+		if (ctrl_init(server, domain, g_username) < 0)
+		{
+			error("Failed to initialize ctrl mode.");
+			exit(1);
+		}
+
+		if (ctrl_is_slave())
+		{
+			fprintf(stdout,
+				"rdesktop in slave mode sending command to master process.\n");
+
+			if (g_seamless_spawn_cmd[0])
+				return ctrl_send_command("seamless.spawn", g_seamless_spawn_cmd);
+
+			fprintf(stdout, "No command specified to be spawn in seamless mode.\n");
+			return EX_USAGE;
+		}
+	}
+
+	if (!ui_init())
+		return EX_OSERR;
+
+#ifdef WITH_RDPSND
+	if (!rdpsnd_init(rdpsnd_optarg))
+		warning("Initializing sound-support failed!\n");
+#endif
+
+	if (g_lspci_enabled)
+		lspci_init();
+
+	rdpdr_init();
+	g_reconnect_loop = False;
+	while (1)
+	{
+		rdesktop_reset_state();
+
+		if (g_redirect)
+		{
+			STRNCPY(domain, g_redirect_domain, sizeof(domain));
+			xfree(g_username);
+			g_username = (char *) xmalloc(strlen(g_redirect_username) + 1);
+			STRNCPY(g_username, g_redirect_username, strlen(g_redirect_username) + 1);
+			STRNCPY(server, g_redirect_server, sizeof(server));
+			flags |= RDP_INFO_AUTOLOGON;
+
+			fprintf(stderr, "Redirected to %s@%s session %d.\n",
+				g_redirect_username, g_redirect_server, g_redirect_session_id);
+
+			/* A redirect on SSL from a 2003 WTS will result in a 'connection reset by peer'
+			   and therefor we just clear this error before we connect to redirected server.
+			 */
+			g_network_error = False;
+			g_redirect = False;
+		}
+
+		ui_init_connection();
+		if (!rdp_connect
+		    (server, flags, domain, g_password, shell, directory, g_reconnect_loop))
+		{
+
+			g_network_error = False;
+
+			if (g_reconnect_loop == False)
+				return EX_PROTOCOL;
+
+			/* check if auto reconnect cookie has timed out */
+			if (time(NULL) - g_reconnect_random_ts > RECONNECT_TIMEOUT)
+			{
+				fprintf(stderr, "Tried to reconnect for %d minutes, giving up.\n",
+					RECONNECT_TIMEOUT / 60);
+				return EX_PROTOCOL;
+			}
+
+			sleep(4);
+			continue;
+		}
+
+		if (g_redirect)
+		{
+			rdp_disconnect();
+			continue;
+		}
+
+		/* By setting encryption to False here, we have an encrypted login 
+		   packet but unencrypted transfer of other packets */
+		if (!g_packet_encryption)
+			g_encryption_initial = g_encryption = False;
+
+		DEBUG(("Connection successful.\n"));
+
+		rd_create_ui();
+		tcp_run_ui(True);
+
+		deactivated = False;
+		g_reconnect_loop = False;
+		rdp_main_loop(&deactivated, &ext_disc_reason);
+
+		tcp_run_ui(False);
+
+		DEBUG(("Disconnecting...\n"));
+		rdp_disconnect();
+
+		if (g_redirect)
+			continue;
+
+		/* handle network error and start autoreconnect */
+		if (g_network_error && !deactivated)
+		{
+			fprintf(stderr,
+				"Disconnected due to network error, retrying to reconnect for %d minutes.\n",
+				RECONNECT_TIMEOUT / 60);
+			g_network_error = False;
+			g_reconnect_loop = True;
+			continue;
+		}
+
+		ui_seamless_end();
+		ui_destroy_window();
+
+		/* Enter a reconnect loop if we have a pending resize request */
+		if (g_pending_resize)
+		{
+			g_pending_resize = False;
+			g_reconnect_loop = True;
+			continue;
+		}
+		break;
+	}
+
+	cache_save_state();
+	ui_deinit();
+
+	if (g_user_quit)
+		return EXRD_WINDOW_CLOSED;
+
+	return handle_disconnect_reason(deactivated, ext_disc_reason);
+
+#endif
+	if (g_redirect_username)
+		xfree(g_redirect_username);
+
+	xfree(g_username);
+}
+
+#ifdef EGD_SOCKET
+/* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
+static RD_BOOL
+generate_random_egd(uint8 * buf)
+{
+	struct sockaddr_un addr;
+	RD_BOOL ret = False;
+	int fd;
+
+	fd = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (fd == -1)
+		return False;
+
+	addr.sun_family = AF_UNIX;
+	memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
+	if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
+		goto err;
+
+	/* PRNGD and EGD use a simple communications protocol */
+	buf[0] = 1;		/* Non-blocking (similar to /dev/urandom) */
+	buf[1] = 32;		/* Number of requested random bytes */
+	if (write(fd, buf, 2) != 2)
+		goto err;
+
+	if ((read(fd, buf, 1) != 1) || (buf[0] == 0))	/* Available? */
+		goto err;
+
+	if (read(fd, buf, 32) != 32)
+		goto err;
+
+	ret = True;
+
+      err:
+	close(fd);
+	return ret;
+}
+#endif
+
+/* Generate a 32-byte random for the secure transport code. */
+void
+generate_random(uint8 * random)
+{
+	struct stat st;
+	struct tms tmsbuf;
+	RDSSL_MD5 md5;
+	uint32 *r;
+	int fd, n;
+
+	/* If we have a kernel random device, try that first */
+	if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
+	    || ((fd = open("/dev/random", O_RDONLY)) != -1))
+	{
+		n = read(fd, random, 32);
+		close(fd);
+		if (n == 32)
+			return;
+	}
+
+#ifdef EGD_SOCKET
+	/* As a second preference use an EGD */
+	if (generate_random_egd(random))
+		return;
+#endif
+
+	/* Otherwise use whatever entropy we can gather - ideas welcome. */
+	r = (uint32 *) random;
+	r[0] = (getpid()) | (getppid() << 16);
+	r[1] = (getuid()) | (getgid() << 16);
+	r[2] = times(&tmsbuf);	/* system uptime (clocks) */
+	gettimeofday((struct timeval *) &r[3], NULL);	/* sec and usec */
+	stat("/tmp", &st);
+	r[5] = st.st_atime;
+	r[6] = st.st_mtime;
+	r[7] = st.st_ctime;
+
+	/* Hash both halves with MD5 to obscure possible patterns */
+	rdssl_md5_init(&md5);
+	rdssl_md5_update(&md5, random, 16);
+	rdssl_md5_final(&md5, random);
+	rdssl_md5_update(&md5, random + 16, 16);
+	rdssl_md5_final(&md5, random + 16);
+}
+
+/* malloc; exit if out of memory */
+void *
+xmalloc(int size)
+{
+	void *mem = malloc(size);
+	if (mem == NULL)
+	{
+		error("xmalloc %d\n", size);
+		exit(EX_UNAVAILABLE);
+	}
+	return mem;
+}
+
+/* Exit on NULL pointer. Use to verify result from XGetImage etc */
+void
+exit_if_null(void *ptr)
+{
+	if (ptr == NULL)
+	{
+		error("unexpected null pointer. Out of memory?\n");
+		exit(EX_UNAVAILABLE);
+	}
+}
+
+/* strdup */
+char *
+xstrdup(const char *s)
+{
+	char *mem = strdup(s);
+	if (mem == NULL)
+	{
+		perror("strdup");
+		exit(EX_UNAVAILABLE);
+	}
+	return mem;
+}
+
+/* realloc; exit if out of memory */
+void *
+xrealloc(void *oldmem, size_t size)
+{
+	void *mem;
+
+	if (size == 0)
+		size = 1;
+	mem = realloc(oldmem, size);
+	if (mem == NULL)
+	{
+		error("xrealloc %ld\n", size);
+		exit(EX_UNAVAILABLE);
+	}
+	return mem;
+}
+
+/* free */
+void
+xfree(void *mem)
+{
+	free(mem);
+}
+
+/* report an error */
+void
+error(char *format, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "ERROR: ");
+
+	va_start(ap, format);
+	vfprintf(stderr, format, ap);
+	va_end(ap);
+}
+
+/* report a warning */
+void
+warning(char *format, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "WARNING: ");
+
+	va_start(ap, format);
+	vfprintf(stderr, format, ap);
+	va_end(ap);
+}
+
+/* report an unimplemented protocol feature */
+void
+unimpl(char *format, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "NOT IMPLEMENTED: ");
+
+	va_start(ap, format);
+	vfprintf(stderr, format, ap);
+	va_end(ap);
+}
+
+/* produce a hex dump */
+void
+hexdump(unsigned char *p, unsigned int len)
+{
+	unsigned char *line = p;
+	int i, thisline, offset = 0;
+
+	while (offset < len)
+	{
+		printf("%04x ", offset);
+		thisline = len - offset;
+		if (thisline > 16)
+			thisline = 16;
+
+		for (i = 0; i < thisline; i++)
+			printf("%02x ", line[i]);
+
+		for (; i < 16; i++)
+			printf("   ");
+
+		for (i = 0; i < thisline; i++)
+			printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
+
+		printf("\n");
+		offset += thisline;
+		line += thisline;
+	}
+}
+
+/*
+  input: src is the string we look in for needle.
+  	 Needle may be escaped by a backslash, in
+	 that case we ignore that particular needle.
+  return value: returns next src pointer, for
+  	succesive executions, like in a while loop
+	if retval is 0, then there are no more args.
+  pitfalls:
+  	src is modified. 0x00 chars are inserted to
+	terminate strings.
+	return val, points on the next val chr after ins
+	0x00
+
+	example usage:
+	while( (pos = next_arg( optarg, ',')) ){
+		printf("%s\n",optarg);
+		optarg=pos;
+	}
+
+*/
+char *
+next_arg(char *src, char needle)
+{
+	char *nextval;
+	char *p;
+	char *mvp = 0;
+
+	/* EOS */
+	if (*src == (char) 0x00)
+		return 0;
+
+	p = src;
+	/*  skip escaped needles */
+	while ((nextval = strchr(p, needle)))
+	{
+		mvp = nextval - 1;
+		/* found backslashed needle */
+		if (*mvp == '\\' && (mvp > src))
+		{
+			/* move string one to the left */
+			while (*(mvp + 1) != (char) 0x00)
+			{
+				*mvp = *(mvp + 1);
+				mvp++;
+			}
+			*mvp = (char) 0x00;
+			p = nextval;
+		}
+		else
+		{
+			p = nextval + 1;
+			break;
+		}
+
+	}
+
+	/* more args available */
+	if (nextval)
+	{
+		*nextval = (char) 0x00;
+		return ++nextval;
+	}
+
+	/* no more args after this, jump to EOS */
+	nextval = src + strlen(src);
+	return nextval;
+}
+
+
+void
+toupper_str(char *p)
+{
+	while (*p)
+	{
+		if ((*p >= 'a') && (*p <= 'z'))
+			*p = toupper((int) *p);
+		p++;
+	}
+}
+
+
+RD_BOOL
+str_startswith(const char *s, const char *prefix)
+{
+	return (strncmp(s, prefix, strlen(prefix)) == 0);
+}
+
+
+/* Split input into lines, and call linehandler for each
+   line. Incomplete lines are saved in the rest variable, which should
+   initially point to NULL. When linehandler returns False, stop and
+   return False. Otherwise, return True.  */
+RD_BOOL
+str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler, void *data)
+{
+	char *buf, *p;
+	char *oldrest;
+	size_t inputlen;
+	size_t buflen;
+	size_t restlen = 0;
+	RD_BOOL ret = True;
+
+	/* Copy data to buffer */
+	inputlen = strlen(input);
+	if (*rest)
+		restlen = strlen(*rest);
+	buflen = restlen + inputlen + 1;
+	buf = (char *) xmalloc(buflen);
+	buf[0] = '\0';
+	if (*rest)
+		STRNCPY(buf, *rest, buflen);
+	strncat(buf, input, inputlen);
+	p = buf;
+
+	while (1)
+	{
+		char *newline = strchr(p, '\n');
+		if (newline)
+		{
+			*newline = '\0';
+			if (!linehandler(p, data))
+			{
+				p = newline + 1;
+				ret = False;
+				break;
+			}
+			p = newline + 1;
+		}
+		else
+		{
+			break;
+
+		}
+	}
+
+	/* Save in rest */
+	oldrest = *rest;
+	restlen = buf + buflen - p;
+	*rest = (char *) xmalloc(restlen);
+	STRNCPY((*rest), p, restlen);
+	xfree(oldrest);
+
+	xfree(buf);
+	return ret;
+}
+
+/* Execute the program specified by argv. For each line in
+   stdout/stderr output, call linehandler. Returns false on failure. */
+RD_BOOL
+subprocess(char *const argv[], str_handle_lines_t linehandler, void *data)
+{
+	pid_t child;
+	int fd[2];
+	int n = 1;
+	char output[256];
+	char *rest = NULL;
+
+	if (pipe(fd) < 0)
+	{
+		perror("pipe");
+		return False;
+	}
+
+	if ((child = fork()) < 0)
+	{
+		perror("fork");
+		return False;
+	}
+
+	/* Child */
+	if (child == 0)
+	{
+		/* Close read end */
+		close(fd[0]);
+
+		/* Redirect stdout and stderr to pipe */
+		dup2(fd[1], 1);
+		dup2(fd[1], 2);
+
+		/* Execute */
+		execvp(argv[0], argv);
+		perror("Error executing child");
+		_exit(128);
+	}
+
+	/* Parent. Close write end. */
+	close(fd[1]);
+	while (n > 0)
+	{
+		n = read(fd[0], output, 255);
+		output[n] = '\0';
+		str_handle_lines(output, &rest, linehandler, data);
+	}
+	xfree(rest);
+
+	return True;
+}
+
+
+/* not all clibs got ltoa */
+#define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
+
+char *
+l_to_a(long N, int base)
+{
+	static char ret[LTOA_BUFSIZE];
+
+	char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
+
+	register int divrem;
+
+	if (base < 36 || 2 > base)
+		base = 10;
+
+	if (N < 0)
+	{
+		*head++ = '-';
+		N = -N;
+	}
+
+	tail = buf + sizeof(buf);
+	*--tail = 0;
+
+	do
+	{
+		divrem = N % base;
+		*--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
+		N /= base;
+	}
+	while (N);
+
+	strcpy(head, tail);
+	return ret;
+}
+
+int
+load_licence(unsigned char **data)
+{
+	uint8 ho[20], hi[16];
+	char *home, path[PATH_MAX], hash[41];
+	struct stat st;
+	int fd, length;
+
+	home = getenv("HOME");
+	if (home == NULL)
+		return -1;
+
+	memset(hi, 0, sizeof(hi));
+	snprintf((char *) hi, 16, "%s", g_hostname);
+	sec_hash_sha1_16(ho, hi, g_static_rdesktop_salt_16);
+	sec_hash_to_string(hash, sizeof(hash), ho, sizeof(ho));
+
+	snprintf(path, PATH_MAX, "%s" RDESKTOP_LICENSE_STORE "/%s.cal", home, hash);
+	path[sizeof(path) - 1] = '\0';
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1)
+	{
+		/* fallback to try reading old license file */
+		snprintf(path, PATH_MAX, "%s/.rdesktop/license.%s", home, g_hostname);
+		path[sizeof(path) - 1] = '\0';
+		if ((fd = open(path, O_RDONLY)) == -1)
+			return -1;
+	}
+
+	if (fstat(fd, &st))
+	{
+		close(fd);
+		return -1;
+	}
+
+	*data = (uint8 *) xmalloc(st.st_size);
+	length = read(fd, *data, st.st_size);
+	close(fd);
+	return length;
+}
+
+void
+save_licence(unsigned char *data, int length)
+{
+	uint8 ho[20], hi[16];
+	char *home, path[PATH_MAX], tmppath[PATH_MAX], hash[41];
+	int fd;
+
+	home = getenv("HOME");
+	if (home == NULL)
+		return;
+
+	snprintf(path, PATH_MAX, "%s" RDESKTOP_LICENSE_STORE, home);
+	path[sizeof(path) - 1] = '\0';
+	if (utils_mkdir_p(path, 0700) == -1)
+	{
+		perror(path);
+		return;
+	}
+
+	memset(hi, 0, sizeof(hi));
+	snprintf((char *) hi, 16, "%s", g_hostname);
+	sec_hash_sha1_16(ho, hi, g_static_rdesktop_salt_16);
+	sec_hash_to_string(hash, sizeof(hash), ho, sizeof(ho));
+
+	/* write licence to {sha1}.cal.new, then atomically 
+	   rename to {sha1}.cal */
+	snprintf(path, PATH_MAX, "%s" RDESKTOP_LICENSE_STORE "/%s.cal", home, hash);
+	path[sizeof(path) - 1] = '\0';
+
+	snprintf(tmppath, PATH_MAX, "%s.new", path);
+	path[sizeof(path) - 1] = '\0';
+
+	fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+	if (fd == -1)
+	{
+		perror(tmppath);
+		return;
+	}
+
+	if (write(fd, data, length) != length)
+	{
+		perror(tmppath);
+		unlink(tmppath);
+	}
+	else if (rename(tmppath, path) == -1)
+	{
+		perror(path);
+		unlink(tmppath);
+	}
+
+	close(fd);
+}
+
+/* create rdesktop ui */
+void
+rd_create_ui()
+{
+	/* only create a window if we dont have one intialized */
+	if (!ui_have_window())
+	{
+		if (!ui_create_window())
+			exit(EX_OSERR);
+	}
+}
+
+/* Create the bitmap cache directory */
+RD_BOOL
+rd_pstcache_mkdir(void)
+{
+	char *home;
+	char bmpcache_dir[256];
+
+	home = getenv("HOME");
+
+	if (home == NULL)
+		return False;
+
+	sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
+
+	if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
+	{
+		perror(bmpcache_dir);
+		return False;
+	}
+
+	sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
+
+	if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
+	{
+		perror(bmpcache_dir);
+		return False;
+	}
+
+	return True;
+}
+
+/* open a file in the .rdesktop directory */
+int
+rd_open_file(char *filename)
+{
+	char *home;
+	char fn[256];
+	int fd;
+
+	home = getenv("HOME");
+	if (home == NULL)
+		return -1;
+	sprintf(fn, "%s/.rdesktop/%s", home, filename);
+	fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+	if (fd == -1)
+		perror(fn);
+	return fd;
+}
+
+/* close file */
+void
+rd_close_file(int fd)
+{
+	close(fd);
+}
+
+/* read from file*/
+int
+rd_read_file(int fd, void *ptr, int len)
+{
+	return read(fd, ptr, len);
+}
+
+/* write to file */
+int
+rd_write_file(int fd, void *ptr, int len)
+{
+	return write(fd, ptr, len);
+}
+
+/* move file pointer */
+int
+rd_lseek_file(int fd, int offset)
+{
+	return lseek(fd, offset, SEEK_SET);
+}
+
+/* do a write lock on a file */
+RD_BOOL
+rd_lock_file(int fd, int start, int len)
+{
+	struct flock lock;
+
+	lock.l_type = F_WRLCK;
+	lock.l_whence = SEEK_SET;
+	lock.l_start = start;
+	lock.l_len = len;
+	if (fcntl(fd, F_SETLK, &lock) == -1)
+		return False;
+	return True;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/rdesktop.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdesktop.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdesktop.h	(revision 55121)
@@ -0,0 +1,218 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   Master include file
+   Copyright (C) Matthew Chapman 1999-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef _WIN32
+#define WINVER 0x0400
+#include <windows.h>
+#include <winsock.h>
+#include <time.h>
+#define DIR int
+#else
+#include <dirent.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#else
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+#endif
+#include <limits.h>		/* PATH_MAX */
+#ifdef HAVE_SYSEXITS_H
+#include <sysexits.h>
+#endif
+
+/* standard exit codes */
+#ifndef EX_OK
+#define EX_OK           0
+#endif
+#ifndef EX_USAGE
+#define EX_USAGE        64
+#endif
+#ifndef EX_DATAERR
+#define EX_DATAERR      65
+#endif
+#ifndef EX_NOINPUT
+#define EX_NOINPUT      66
+#endif
+#ifndef EX_NOUSER
+#define EX_NOUSER       67
+#endif
+#ifndef EX_NOHOST
+#define EX_NOHOST       68
+#endif
+#ifndef EX_UNAVAILABLE
+#define EX_UNAVAILABLE  69
+#endif
+#ifndef EX_SOFTWARE
+#define EX_SOFTWARE     70
+#endif
+#ifndef EX_OSERR
+#define EX_OSERR        71
+#endif
+#ifndef EX_OSFILE
+#define EX_OSFILE       72
+#endif
+#ifndef EX_CANTCREAT
+#define EX_CANTCREAT    73
+#endif
+#ifndef EX_IOERR
+#define EX_IOERR        74
+#endif
+#ifndef EX_TEMPFAIL
+#define EX_TEMPFAIL     75
+#endif
+#ifndef EX_PROTOCOL
+#define EX_PROTOCOL     76
+#endif
+#ifndef EX_NOPERM
+#define EX_NOPERM       77
+#endif
+#ifndef EX_CONFIG
+#define EX_CONFIG       78
+#endif
+
+/* rdesktop specific exit codes, lined up with disconnect PDU reasons */
+#define EXRD_API_DISCONNECT 1
+#define EXRD_API_LOGOFF 2
+#define EXRD_IDLE_TIMEOUT 3
+#define EXRD_LOGON_TIMEOUT 4
+#define EXRD_REPLACED 5
+#define EXRD_OUT_OF_MEM 6
+#define EXRD_DENIED 7
+#define EXRD_DENIED_FIPS 8
+#define EXRD_INSUFFICIENT_PRIVILEGES 9
+#define EXRD_FRESH_CREDENTIALS_REQUIRED 10
+#define EXRD_RPC_DISCONNECT_BY_USER 11
+#define EXRD_DISCONNECT_BY_USER 12
+#define EXRD_LIC_INTERNAL 16
+#define EXRD_LIC_NOSERVER 17
+#define EXRD_LIC_NOLICENSE 18
+#define EXRD_LIC_MSG 19
+#define EXRD_LIC_HWID 20
+#define EXRD_LIC_CLIENT 21
+#define EXRD_LIC_NET 22
+#define EXRD_LIC_PROTO 23
+#define EXRD_LIC_ENC 24
+#define EXRD_LIC_UPGRADE 25
+#define EXRD_LIC_NOREMOTE 26
+
+/* other exit codes */
+#define EXRD_WINDOW_CLOSED 62
+#define EXRD_UNKNOWN 63
+
+#ifdef WITH_DEBUG
+#define DEBUG(args)	printf args;
+#else
+#define DEBUG(args)
+#endif
+
+#ifdef WITH_DEBUG_KBD
+#define DEBUG_KBD(args) printf args;
+#else
+#define DEBUG_KBD(args)
+#endif
+
+#ifdef WITH_DEBUG_RDP5
+#define DEBUG_RDP5(args) printf args;
+#else
+#define DEBUG_RDP5(args)
+#endif
+
+#ifdef WITH_DEBUG_CLIPBOARD
+#define DEBUG_CLIPBOARD(args) printf args;
+#else
+#define DEBUG_CLIPBOARD(args)
+#endif
+
+#ifdef WITH_DEBUG_SOUND
+#define DEBUG_SOUND(args) printf args;
+#else
+#define DEBUG_SOUND(args)
+#endif
+
+#ifdef WITH_DEBUG_CHANNEL
+#define DEBUG_CHANNEL(args) printf args;
+#else
+#define DEBUG_CHANNEL(args)
+#endif
+
+#ifdef WITH_DEBUG_SCARD
+#define DEBUG_SCARD(args) printf args;
+#else
+#define DEBUG_SCARD(args)
+#endif
+
+#define STRNCPY(dst,src,n)	{ strncpy(dst,src,n-1); dst[n-1] = 0; }
+
+#ifndef MIN
+#define MIN(x,y)		(((x) < (y)) ? (x) : (y))
+#endif
+
+#ifndef MAX
+#define MAX(x,y)		(((x) > (y)) ? (x) : (y))
+#endif
+
+/* timeval macros */
+#ifndef timerisset
+#define timerisset(tvp)\
+         ((tvp)->tv_sec || (tvp)->tv_usec)
+#endif
+#ifndef timercmp
+#define timercmp(tvp, uvp, cmp)\
+        ((tvp)->tv_sec cmp (uvp)->tv_sec ||\
+        (tvp)->tv_sec == (uvp)->tv_sec &&\
+        (tvp)->tv_usec cmp (uvp)->tv_usec)
+#endif
+#ifndef timerclear
+#define timerclear(tvp)\
+        ((tvp)->tv_sec = (tvp)->tv_usec = 0)
+#endif
+
+/* If configure does not define the endianess, try
+   to find it out */
+#if !defined(L_ENDIAN) && !defined(B_ENDIAN)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define L_ENDIAN
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define B_ENDIAN
+#else
+#error Unknown endianness. Edit rdesktop.h.
+#endif
+#endif /* B_ENDIAN, L_ENDIAN from configure */
+
+/* No need for alignment on x86 and amd64 */
+#if !defined(NEED_ALIGN)
+#if !(defined(__x86__) || defined(__x86_64__) || \
+      defined(__AMD64__) || defined(_M_IX86) || \
+      defined(__i386__))
+#define NEED_ALIGN
+#endif
+#endif
+
+#include "parse.h"
+#include "constants.h"
+#include "types.h"
+
+#ifndef MAKE_PROTO
+#include "proto.h"
+#endif
Index: /trunk/src/VBox/RDP/client-1.8.3/rdesktop.spec
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdesktop.spec	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdesktop.spec	(revision 55121)
@@ -0,0 +1,36 @@
+Summary: Remote Desktop Protocol client
+Name: rdesktop
+Version: 1.8.3
+Release: 1
+License: GPL; see COPYING
+Group: Applications/Communications
+Source: rdesktop-%{version}.tar.gz
+BuildRoot: %{_tmppath}/%{name}-buildroot
+Packager: Peter Åstrand <astrand@cendio.se>
+
+%description
+rdesktop is a client for Remote Desktop Protocol (RDP), used in a number of
+Microsoft products including Windows NT Terminal Server, Windows 2000 Server,
+Windows XP, Windows 2003 Server and Windows 2008r2.
+
+%prep
+rm -rf $RPM_BUILD_ROOT
+
+%setup
+%build 
+./configure --prefix=%{_prefix} --bindir=%{_bindir} --mandir=%{_mandir}
+make
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc COPYING doc/AUTHORS doc/keymapping.txt doc/keymap-names.txt doc/ipv6.txt doc/ChangeLog
+%{_bindir}/rdesktop
+%{_mandir}/man1/rdesktop.1*
+%{_datadir}/rdesktop/keymaps
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
Index: /trunk/src/VBox/RDP/client-1.8.3/rdp.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdp.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdp.c	(revision 55121)
@@ -0,0 +1,1776 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - RDP layer
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright 2003-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+   Copyright 2011-2014 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <time.h>
+#ifndef _WIN32
+#include <errno.h>
+#include <unistd.h>
+#endif
+#include "rdesktop.h"
+#include "ssl.h"
+
+#ifdef HAVE_ICONV
+#ifdef HAVE_ICONV_H
+#include <iconv.h>
+#endif
+
+#ifndef ICONV_CONST
+#define ICONV_CONST ""
+#endif
+#endif
+
+extern uint16 g_mcs_userid;
+extern char *g_username;
+extern char g_password[64];
+extern char g_codepage[16];
+extern RD_BOOL g_bitmap_compression;
+extern RD_BOOL g_orders;
+extern RD_BOOL g_encryption;
+extern RD_BOOL g_desktop_save;
+extern RD_BOOL g_polygon_ellipse_orders;
+extern RDP_VERSION g_rdp_version;
+extern uint16 g_server_rdp_version;
+extern uint32 g_rdp5_performanceflags;
+extern int g_server_depth;
+extern int g_width;
+extern int g_height;
+extern RD_BOOL g_bitmap_cache;
+extern RD_BOOL g_bitmap_cache_persist_enable;
+extern RD_BOOL g_numlock_sync;
+extern RD_BOOL g_pending_resize;
+extern RD_BOOL g_network_error;
+
+uint8 *g_next_packet;
+uint32 g_rdp_shareid;
+
+extern RDPCOMP g_mppc_dict;
+
+/* Session Directory support */
+extern RD_BOOL g_redirect;
+extern char *g_redirect_server;
+extern uint32 g_redirect_server_len;
+extern char *g_redirect_domain;
+extern uint32 g_redirect_domain_len;
+extern char *g_redirect_username;
+extern uint32 g_redirect_username_len;
+extern uint8 *g_redirect_lb_info;
+extern uint32 g_redirect_lb_info_len;
+extern uint8 *g_redirect_cookie;
+extern uint32 g_redirect_cookie_len;
+extern uint32 g_redirect_flags;
+extern uint32 g_redirect_session_id;
+
+/* END Session Directory support */
+
+extern uint32 g_reconnect_logonid;
+extern char g_reconnect_random[16];
+extern time_t g_reconnect_random_ts;
+extern RD_BOOL g_has_reconnect_random;
+extern uint8 g_client_random[SEC_RANDOM_SIZE];
+
+#if WITH_DEBUG
+static uint32 g_packetno;
+#endif
+
+#ifdef HAVE_ICONV
+static RD_BOOL g_iconv_works = True;
+#endif
+
+/* Receive an RDP packet */
+static STREAM
+rdp_recv(uint8 * type)
+{
+	static STREAM rdp_s;
+	uint16 length, pdu_type;
+	uint8 rdpver;
+
+	if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL))
+	{
+		rdp_s = sec_recv(&rdpver);
+		if (rdp_s == NULL)
+			return NULL;
+		if (rdpver == 0xff)
+		{
+			g_next_packet = rdp_s->end;
+			*type = 0;
+			return rdp_s;
+		}
+		else if (rdpver != 3)
+		{
+			/* rdp5_process should move g_next_packet ok */
+			rdp5_process(rdp_s);
+			*type = 0;
+			return rdp_s;
+		}
+
+		g_next_packet = rdp_s->p;
+	}
+	else
+	{
+		rdp_s->p = g_next_packet;
+	}
+
+	in_uint16_le(rdp_s, length);
+	/* 32k packets are really 8, keepalive fix */
+	if (length == 0x8000)
+	{
+		g_next_packet += 8;
+		*type = 0;
+		return rdp_s;
+	}
+	in_uint16_le(rdp_s, pdu_type);
+	in_uint8s(rdp_s, 2);	/* userid */
+	*type = pdu_type & 0xf;
+
+#if WITH_DEBUG
+	DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
+	hexdump(g_next_packet, length);
+#endif /*  */
+
+	g_next_packet += length;
+	return rdp_s;
+}
+
+/* Initialise an RDP data packet */
+static STREAM
+rdp_init_data(int maxlen)
+{
+	STREAM s;
+
+	s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
+	s_push_layer(s, rdp_hdr, 18);
+
+	return s;
+}
+
+/* Send an RDP data packet */
+static void
+rdp_send_data(STREAM s, uint8 data_pdu_type)
+{
+	uint16 length;
+
+	s_pop_layer(s, rdp_hdr);
+	length = s->end - s->p;
+
+	out_uint16_le(s, length);
+	out_uint16_le(s, (RDP_PDU_DATA | 0x10));
+	out_uint16_le(s, (g_mcs_userid + 1001));
+
+	out_uint32_le(s, g_rdp_shareid);
+	out_uint8(s, 0);	/* pad */
+	out_uint8(s, 1);	/* streamid */
+	out_uint16_le(s, (length - 14));
+	out_uint8(s, data_pdu_type);
+	out_uint8(s, 0);	/* compress_type */
+	out_uint16(s, 0);	/* compress_len */
+
+	sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
+}
+
+/* Output a string in Unicode */
+void
+rdp_out_unistr(STREAM s, char *string, int len)
+{
+	if (string == NULL || len == 0)
+		return;
+
+#ifdef HAVE_ICONV
+	size_t ibl = strlen(string), obl = len + 2;
+	static iconv_t iconv_h = (iconv_t) - 1;
+	char *pin = string, *pout = (char *) s->p;
+
+	memset(pout, 0, len + 4);
+
+	if (g_iconv_works)
+	{
+		if (iconv_h == (iconv_t) - 1)
+		{
+			size_t i = 1, o = 4;
+			if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)
+			{
+				warning("rdp_out_unistr: iconv_open[%s -> %s] fail %p\n",
+					g_codepage, WINDOWS_CODEPAGE, iconv_h);
+
+				g_iconv_works = False;
+				rdp_out_unistr(s, string, len);
+				return;
+			}
+			if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) ==
+			    (size_t) - 1)
+			{
+				iconv_close(iconv_h);
+				iconv_h = (iconv_t) - 1;
+				warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
+
+				g_iconv_works = False;
+				rdp_out_unistr(s, string, len);
+				return;
+			}
+			pin = string;
+			pout = (char *) s->p;
+		}
+
+		if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
+		{
+			iconv_close(iconv_h);
+			iconv_h = (iconv_t) - 1;
+			warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);
+
+			g_iconv_works = False;
+			rdp_out_unistr(s, string, len);
+			return;
+		}
+
+		s->p += len + 2;
+
+	}
+	else
+#endif
+	{
+		int i = 0, j = 0;
+
+		len += 2;
+
+		while (i < len)
+		{
+			s->p[i++] = string[j++];
+			s->p[i++] = 0;
+		}
+
+		s->p += len;
+	}
+}
+
+/* Input a string in Unicode
+ *
+ * Returns str_len of string
+ */
+void
+rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
+{
+	/* Dynamic allocate of destination string if not provided */
+	*string = xmalloc(in_len * 2);
+	*str_size = in_len * 2;
+
+#ifdef HAVE_ICONV
+	size_t ibl = in_len, obl = *str_size - 1;
+	char *pin = (char *) s->p, *pout = *string;
+	static iconv_t iconv_h = (iconv_t) - 1;
+
+	if (g_iconv_works)
+	{
+		if (iconv_h == (iconv_t) - 1)
+		{
+			if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)
+			{
+				warning("rdp_in_unistr: iconv_open[%s -> %s] fail %p\n",
+					WINDOWS_CODEPAGE, g_codepage, iconv_h);
+
+				g_iconv_works = False;
+				return rdp_in_unistr(s, in_len, string, str_size);
+			}
+		}
+
+		if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
+		{
+			if (errno == E2BIG)
+			{
+				warning("server sent an unexpectedly long string, truncating\n");
+			}
+			else
+			{
+				warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
+
+				free(*string);
+				*string = NULL;
+				*str_size = 0;
+			}
+		}
+
+		/* we must update the location of the current STREAM for future reads of s->p */
+		s->p += in_len;
+
+		*pout = 0;
+
+		if (*string)
+			*str_size = pout - *string;
+	}
+	else
+#endif
+	{
+		int i = 0;
+		int rem = 0;
+		uint32 len = in_len / 2;
+
+		if (len > *str_size - 1)
+		{
+			warning("server sent an unexpectedly long string, truncating\n");
+			len = *str_size - 1;
+			rem = in_len - 2 * len;
+		}
+
+		while (i < len)
+		{
+			in_uint8a(s, &string[i++], 1);
+			in_uint8s(s, 1);
+		}
+
+		in_uint8s(s, rem);
+		string[len] = 0;
+		*str_size = len;
+	}
+}
+
+
+/* Parse a logon info packet */
+static void
+rdp_send_logon_info(uint32 flags, char *domain, char *user,
+		    char *password, char *program, char *directory)
+{
+	char *ipaddr = tcp_get_address();
+	/* length of string in TS_INFO_PACKET excludes null terminator */
+	int len_domain = 2 * strlen(domain);
+	int len_user = 2 * strlen(user);
+	int len_password = 2 * strlen(password);
+	int len_program = 2 * strlen(program);
+	int len_directory = 2 * strlen(directory);
+
+	/* length of strings in TS_EXTENDED_PACKET includes null terminator */
+	int len_ip = 2 * strlen(ipaddr) + 2;
+	int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll") + 2;
+
+	int packetlen = 0;
+	uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
+	STREAM s;
+	time_t t = time(NULL);
+	time_t tzone;
+	uint8 security_verifier[16];
+
+	if (g_rdp_version == RDP_V4 || 1 == g_server_rdp_version)
+	{
+		DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
+
+		s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
+			     + len_program + len_directory + 10);
+
+		out_uint32(s, 0);
+		out_uint32_le(s, flags);
+		out_uint16_le(s, len_domain);
+		out_uint16_le(s, len_user);
+		out_uint16_le(s, len_password);
+		out_uint16_le(s, len_program);
+		out_uint16_le(s, len_directory);
+		rdp_out_unistr(s, domain, len_domain);
+		rdp_out_unistr(s, user, len_user);
+		rdp_out_unistr(s, password, len_password);
+		rdp_out_unistr(s, program, len_program);
+		rdp_out_unistr(s, directory, len_directory);
+	}
+	else
+	{
+
+		DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
+
+		if (g_redirect == True && g_redirect_cookie_len > 0)
+		{
+			len_password = g_redirect_cookie_len;
+			len_password -= 2;	/* substract 2 bytes which is added below */
+		}
+
+		packetlen =
+			/* size of TS_INFO_PACKET */
+			4 +	/* CodePage */
+			4 +	/* flags */
+			2 +	/* cbDomain */
+			2 +	/* cbUserName */
+			2 +	/* cbPassword */
+			2 +	/* cbAlternateShell */
+			2 +	/* cbWorkingDir */
+			2 + len_domain +	/* Domain */
+			2 + len_user +	/* UserName */
+			2 + len_password +	/* Password */
+			2 + len_program +	/* AlternateShell */
+			2 + len_directory +	/* WorkingDir */
+			/* size of TS_EXTENDED_INFO_PACKET */
+			2 +	/* clientAdressFamily */
+			2 +	/* cbClientAdress */
+			len_ip +	/* clientAddress */
+			2 +	/* cbClientDir */
+			len_dll +	/* clientDir */
+			/* size of TS_TIME_ZONE_INFORMATION */
+			4 +	/* Bias, (UTC = local time + bias */
+			64 +	/* StandardName, 32 unicode char array, Descriptive standard time on client */
+			16 +	/* StandardDate */
+			4 +	/* StandardBias */
+			64 +	/* DaylightName, 32 unicode char array */
+			16 +	/* DaylightDate */
+			4 +	/* DaylightBias */
+			4 +	/* clientSessionId */
+			4 +	/* performanceFlags */
+			2 +	/* cbAutoReconnectCookie, either 0 or 0x001c */
+			/* size of ARC_CS_PRIVATE_PACKET */
+			28;	/* autoReconnectCookie */
+
+
+		s = sec_init(sec_flags, packetlen);
+		DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
+
+		/* TS_INFO_PACKET */
+		out_uint32(s, 0);	/* Code Page */
+		out_uint32_le(s, flags);
+		out_uint16_le(s, len_domain);
+		out_uint16_le(s, len_user);
+		out_uint16_le(s, len_password);
+		out_uint16_le(s, len_program);
+		out_uint16_le(s, len_directory);
+
+		if (0 < len_domain)
+			rdp_out_unistr(s, domain, len_domain);
+		else
+			out_uint16_le(s, 0);	/* mandatory 2 bytes null terminator */
+
+		if (0 < len_user)
+			rdp_out_unistr(s, user, len_user);
+		else
+			out_uint16_le(s, 0);	/* mandatory 2 bytes null terminator */
+
+		if (0 < len_password)
+		{
+			if (g_redirect == True && 0 < g_redirect_cookie_len)
+			{
+				out_uint8p(s, g_redirect_cookie, g_redirect_cookie_len);
+			}
+			else
+			{
+				rdp_out_unistr(s, password, len_password);
+			}
+		}
+		else
+			out_uint16_le(s, 0);	/* mandatory 2 bytes null terminator */
+
+		if (0 < len_program)
+			rdp_out_unistr(s, program, len_program);
+		else
+			out_uint16_le(s, 0);	/* mandatory 2 bytes null terminator */
+
+		if (0 < len_directory)
+			rdp_out_unistr(s, directory, len_directory);
+		else
+			out_uint16_le(s, 0);	/* mandatory 2 bytes null terminator */
+
+		/* TS_EXTENDED_INFO_PACKET */
+		out_uint16_le(s, 2);	/* clientAddressFamily = AF_INET */
+		out_uint16_le(s, len_ip);	/* cbClientAddress, Length of client ip */
+		rdp_out_unistr(s, ipaddr, len_ip - 2);	/* clientAddress */
+		out_uint16_le(s, len_dll);	/* cbClientDir */
+		rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll - 2);	/* clientDir */
+
+		/* TS_TIME_ZONE_INFORMATION */
+		tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
+		out_uint32_le(s, tzone);
+		rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
+		out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
+		out_uint32_le(s, 0x0a0000);
+		out_uint32_le(s, 0x050000);
+		out_uint32_le(s, 3);
+		out_uint32_le(s, 0);
+		out_uint32_le(s, 0);
+		rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
+		out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
+		out_uint32_le(s, 0x30000);
+		out_uint32_le(s, 0x050000);
+		out_uint32_le(s, 2);
+		out_uint32(s, 0);
+		out_uint32_le(s, 0xffffffc4);	/* DaylightBias */
+
+		/* Rest of TS_EXTENDED_INFO_PACKET */
+		out_uint32_le(s, 0);	/* clientSessionId (Ignored by server MUST be 0) */
+		out_uint32_le(s, g_rdp5_performanceflags);
+
+		/* Client Auto-Reconnect */
+		if (g_has_reconnect_random)
+		{
+			out_uint16_le(s, 28);	/* cbAutoReconnectLen */
+			/* ARC_CS_PRIVATE_PACKET */
+			out_uint32_le(s, 28);	/* cbLen */
+			out_uint32_le(s, 1);	/* Version */
+			out_uint32_le(s, g_reconnect_logonid);	/* LogonId */
+			rdssl_hmac_md5(g_reconnect_random, sizeof(g_reconnect_random),
+				       g_client_random, SEC_RANDOM_SIZE, security_verifier);
+			out_uint8a(s, security_verifier, sizeof(security_verifier));
+		}
+		else
+		{
+			out_uint16_le(s, 0);	/* cbAutoReconnectLen */
+		}
+
+	}
+	s_mark_end(s);
+
+	/* clear the redirect flag */
+	g_redirect = False;
+
+	sec_send(s, sec_flags);
+}
+
+/* Send a control PDU */
+static void
+rdp_send_control(uint16 action)
+{
+	STREAM s;
+
+	s = rdp_init_data(8);
+
+	out_uint16_le(s, action);
+	out_uint16(s, 0);	/* userid */
+	out_uint32(s, 0);	/* control id */
+
+	s_mark_end(s);
+	rdp_send_data(s, RDP_DATA_PDU_CONTROL);
+}
+
+/* Send a synchronisation PDU */
+static void
+rdp_send_synchronise(void)
+{
+	STREAM s;
+
+	s = rdp_init_data(4);
+
+	out_uint16_le(s, 1);	/* type */
+	out_uint16_le(s, 1002);
+
+	s_mark_end(s);
+	rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
+}
+
+/* Send a single input event */
+void
+rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
+{
+	STREAM s;
+
+	s = rdp_init_data(16);
+
+	out_uint16_le(s, 1);	/* number of events */
+	out_uint16(s, 0);	/* pad */
+
+	out_uint32_le(s, time);
+	out_uint16_le(s, message_type);
+	out_uint16_le(s, device_flags);
+	out_uint16_le(s, param1);
+	out_uint16_le(s, param2);
+
+	s_mark_end(s);
+	rdp_send_data(s, RDP_DATA_PDU_INPUT);
+}
+
+/* Send a client window information PDU */
+void
+rdp_send_client_window_status(int status)
+{
+	STREAM s;
+	static int current_status = 1;
+
+	if (current_status == status)
+		return;
+
+	s = rdp_init_data(12);
+
+	out_uint32_le(s, status);
+
+	switch (status)
+	{
+		case 0:	/* shut the server up */
+			break;
+
+		case 1:	/* receive data again */
+			out_uint32_le(s, 0);	/* unknown */
+			out_uint16_le(s, g_width);
+			out_uint16_le(s, g_height);
+			break;
+	}
+
+	s_mark_end(s);
+	rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
+	current_status = status;
+}
+
+/* Send persistent bitmap cache enumeration PDU's */
+static void
+rdp_enum_bmpcache2(void)
+{
+	STREAM s;
+	HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
+	uint32 num_keys, offset, count, flags;
+
+	offset = 0;
+	num_keys = pstcache_enumerate(2, keylist);
+
+	while (offset < num_keys)
+	{
+		count = MIN(num_keys - offset, 169);
+
+		s = rdp_init_data(24 + count * sizeof(HASH_KEY));
+
+		flags = 0;
+		if (offset == 0)
+			flags |= PDU_FLAG_FIRST;
+		if (num_keys - offset <= 169)
+			flags |= PDU_FLAG_LAST;
+
+		/* header */
+		out_uint32_le(s, 0);
+		out_uint16_le(s, count);
+		out_uint16_le(s, 0);
+		out_uint16_le(s, 0);
+		out_uint16_le(s, 0);
+		out_uint16_le(s, 0);
+		out_uint16_le(s, num_keys);
+		out_uint32_le(s, 0);
+		out_uint32_le(s, flags);
+
+		/* list */
+		out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
+
+		s_mark_end(s);
+		rdp_send_data(s, 0x2b);
+
+		offset += 169;
+	}
+}
+
+/* Send an (empty) font information PDU */
+static void
+rdp_send_fonts(uint16 seq)
+{
+	STREAM s;
+
+	s = rdp_init_data(8);
+
+	out_uint16(s, 0);	/* number of fonts */
+	out_uint16_le(s, 0);	/* pad? */
+	out_uint16_le(s, seq);	/* unknown */
+	out_uint16_le(s, 0x32);	/* entry size */
+
+	s_mark_end(s);
+	rdp_send_data(s, RDP_DATA_PDU_FONT2);
+}
+
+/* Output general capability set */
+static void
+rdp_out_general_caps(STREAM s)
+{
+	out_uint16_le(s, RDP_CAPSET_GENERAL);
+	out_uint16_le(s, RDP_CAPLEN_GENERAL);
+
+	out_uint16_le(s, 1);	/* OS major type */
+	out_uint16_le(s, 3);	/* OS minor type */
+	out_uint16_le(s, 0x200);	/* Protocol version */
+	out_uint16(s, 0);	/* Pad */
+	out_uint16(s, 0);	/* Compression types */
+	out_uint16_le(s, (g_rdp_version >= RDP_V5) ? 0x40d : 0);
+	/* Pad, according to T.128. 0x40d seems to 
+	   trigger
+	   the server to start sending RDP5 packets. 
+	   However, the value is 0x1d04 with W2KTSK and
+	   NT4MS. Hmm.. Anyway, thankyou, Microsoft,
+	   for sending such information in a padding 
+	   field.. */
+	out_uint16(s, 0);	/* Update capability */
+	out_uint16(s, 0);	/* Remote unshare capability */
+	out_uint16(s, 0);	/* Compression level */
+	out_uint16(s, 0);	/* Pad */
+}
+
+/* Output bitmap capability set */
+static void
+rdp_out_bitmap_caps(STREAM s)
+{
+	out_uint16_le(s, RDP_CAPSET_BITMAP);
+	out_uint16_le(s, RDP_CAPLEN_BITMAP);
+
+	out_uint16_le(s, g_server_depth);	/* Preferred colour depth */
+	out_uint16_le(s, 1);	/* Receive 1 BPP */
+	out_uint16_le(s, 1);	/* Receive 4 BPP */
+	out_uint16_le(s, 1);	/* Receive 8 BPP */
+	out_uint16_le(s, 800);	/* Desktop width */
+	out_uint16_le(s, 600);	/* Desktop height */
+	out_uint16(s, 0);	/* Pad */
+	out_uint16(s, 1);	/* Allow resize */
+	out_uint16_le(s, g_bitmap_compression ? 1 : 0);	/* Support compression */
+	out_uint16(s, 0);	/* Unknown */
+	out_uint16_le(s, 1);	/* Unknown */
+	out_uint16(s, 0);	/* Pad */
+}
+
+/* Output order capability set */
+static void
+rdp_out_order_caps(STREAM s)
+{
+	uint8 order_caps[32];
+
+	memset(order_caps, 0, 32);
+	order_caps[0] = 1;	/* dest blt */
+	order_caps[1] = 1;	/* pat blt */
+	order_caps[2] = 1;	/* screen blt */
+	order_caps[3] = (g_bitmap_cache ? 1 : 0);	/* memblt */
+	order_caps[4] = 0;	/* triblt */
+	order_caps[8] = 1;	/* line */
+	order_caps[9] = 1;	/* line */
+	order_caps[10] = 1;	/* rect */
+	order_caps[11] = (g_desktop_save ? 1 : 0);	/* desksave */
+	order_caps[13] = 1;	/* memblt */
+	order_caps[14] = 1;	/* triblt */
+	order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);	/* polygon */
+	order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);	/* polygon2 */
+	order_caps[22] = 1;	/* polyline */
+	order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);	/* ellipse */
+	order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);	/* ellipse2 */
+	order_caps[27] = 1;	/* text2 */
+	out_uint16_le(s, RDP_CAPSET_ORDER);
+	out_uint16_le(s, RDP_CAPLEN_ORDER);
+
+	out_uint8s(s, 20);	/* Terminal desc, pad */
+	out_uint16_le(s, 1);	/* Cache X granularity */
+	out_uint16_le(s, 20);	/* Cache Y granularity */
+	out_uint16(s, 0);	/* Pad */
+	out_uint16_le(s, 1);	/* Max order level */
+	out_uint16_le(s, 0x147);	/* Number of fonts */
+	out_uint16_le(s, 0x2a);	/* Capability flags */
+	out_uint8p(s, order_caps, 32);	/* Orders supported */
+	out_uint16_le(s, 0x6a1);	/* Text capability flags */
+	out_uint8s(s, 6);	/* Pad */
+	out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);	/* Desktop cache size */
+	out_uint32(s, 0);	/* Unknown */
+	out_uint32_le(s, 0x4e4);	/* Unknown */
+}
+
+/* Output bitmap cache capability set */
+static void
+rdp_out_bmpcache_caps(STREAM s)
+{
+	int Bpp;
+	out_uint16_le(s, RDP_CAPSET_BMPCACHE);
+	out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
+
+	Bpp = (g_server_depth + 7) / 8;	/* bytes per pixel */
+	out_uint8s(s, 24);	/* unused */
+	out_uint16_le(s, 0x258);	/* entries */
+	out_uint16_le(s, 0x100 * Bpp);	/* max cell size */
+	out_uint16_le(s, 0x12c);	/* entries */
+	out_uint16_le(s, 0x400 * Bpp);	/* max cell size */
+	out_uint16_le(s, 0x106);	/* entries */
+	out_uint16_le(s, 0x1000 * Bpp);	/* max cell size */
+}
+
+/* Output bitmap cache v2 capability set */
+static void
+rdp_out_bmpcache2_caps(STREAM s)
+{
+	out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
+	out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
+
+	out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);	/* version */
+
+	out_uint16_be(s, 3);	/* number of caches in this set */
+
+	/* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
+	out_uint32_le(s, BMPCACHE2_C0_CELLS);
+	out_uint32_le(s, BMPCACHE2_C1_CELLS);
+	if (pstcache_init(2))
+	{
+		out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
+	}
+	else
+	{
+		out_uint32_le(s, BMPCACHE2_C2_CELLS);
+	}
+	out_uint8s(s, 20);	/* other bitmap caches not used */
+}
+
+/* Output control capability set */
+static void
+rdp_out_control_caps(STREAM s)
+{
+	out_uint16_le(s, RDP_CAPSET_CONTROL);
+	out_uint16_le(s, RDP_CAPLEN_CONTROL);
+
+	out_uint16(s, 0);	/* Control capabilities */
+	out_uint16(s, 0);	/* Remote detach */
+	out_uint16_le(s, 2);	/* Control interest */
+	out_uint16_le(s, 2);	/* Detach interest */
+}
+
+/* Output activation capability set */
+static void
+rdp_out_activate_caps(STREAM s)
+{
+	out_uint16_le(s, RDP_CAPSET_ACTIVATE);
+	out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
+
+	out_uint16(s, 0);	/* Help key */
+	out_uint16(s, 0);	/* Help index key */
+	out_uint16(s, 0);	/* Extended help key */
+	out_uint16(s, 0);	/* Window activate */
+}
+
+/* Output pointer capability set */
+static void
+rdp_out_pointer_caps(STREAM s)
+{
+	out_uint16_le(s, RDP_CAPSET_POINTER);
+	out_uint16_le(s, RDP_CAPLEN_POINTER);
+
+	out_uint16(s, 0);	/* Colour pointer */
+	out_uint16_le(s, 20);	/* Cache size */
+}
+
+/* Output new pointer capability set */
+static void
+rdp_out_newpointer_caps(STREAM s)
+{
+	out_uint16_le(s, RDP_CAPSET_POINTER);
+	out_uint16_le(s, RDP_CAPLEN_NEWPOINTER);
+
+	out_uint16_le(s, 1);	/* Colour pointer */
+	out_uint16_le(s, 20);	/* Cache size */
+	out_uint16_le(s, 20);	/* Cache size for new pointers */
+}
+
+/* Output share capability set */
+static void
+rdp_out_share_caps(STREAM s)
+{
+	out_uint16_le(s, RDP_CAPSET_SHARE);
+	out_uint16_le(s, RDP_CAPLEN_SHARE);
+
+	out_uint16(s, 0);	/* userid */
+	out_uint16(s, 0);	/* pad */
+}
+
+/* Output colour cache capability set */
+static void
+rdp_out_colcache_caps(STREAM s)
+{
+	out_uint16_le(s, RDP_CAPSET_COLCACHE);
+	out_uint16_le(s, RDP_CAPLEN_COLCACHE);
+
+	out_uint16_le(s, 6);	/* cache size */
+	out_uint16(s, 0);	/* pad */
+}
+
+/* Output brush cache capability set */
+static void
+rdp_out_brushcache_caps(STREAM s)
+{
+	out_uint16_le(s, RDP_CAPSET_BRUSHCACHE);
+	out_uint16_le(s, RDP_CAPLEN_BRUSHCACHE);
+	out_uint32_le(s, 1);	/* cache type */
+}
+
+static uint8 caps_0x0d[] = {
+	0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
+	0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00
+};
+
+static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
+
+static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
+
+static uint8 caps_0x10[] = {
+	0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
+	0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
+	0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
+	0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
+	0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
+	0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
+};
+
+/* Output unknown capability sets */
+static void
+rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
+{
+	out_uint16_le(s, id);
+	out_uint16_le(s, length);
+
+	out_uint8p(s, caps, length - 4);
+}
+
+#define RDP5_FLAG 0x0030
+/* Send a confirm active PDU */
+static void
+rdp_send_confirm_active(void)
+{
+	STREAM s;
+	uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
+	uint16 caplen =
+		RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
+		RDP_CAPLEN_COLCACHE +
+		RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
+		RDP_CAPLEN_SHARE +
+		RDP_CAPLEN_BRUSHCACHE + 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
+		4 /* w2k fix, sessionid */ ;
+
+	if (g_rdp_version >= RDP_V5)
+	{
+		caplen += RDP_CAPLEN_BMPCACHE2;
+		caplen += RDP_CAPLEN_NEWPOINTER;
+	}
+	else
+	{
+		caplen += RDP_CAPLEN_BMPCACHE;
+		caplen += RDP_CAPLEN_POINTER;
+	}
+
+	s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
+
+	out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
+	out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));	/* Version 1 */
+	out_uint16_le(s, (g_mcs_userid + 1001));
+
+	out_uint32_le(s, g_rdp_shareid);
+	out_uint16_le(s, 0x3ea);	/* userid */
+	out_uint16_le(s, sizeof(RDP_SOURCE));
+	out_uint16_le(s, caplen);
+
+	out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
+	out_uint16_le(s, 0xe);	/* num_caps */
+	out_uint8s(s, 2);	/* pad */
+
+	rdp_out_general_caps(s);
+	rdp_out_bitmap_caps(s);
+	rdp_out_order_caps(s);
+	if (g_rdp_version >= RDP_V5)
+	{
+		rdp_out_bmpcache2_caps(s);
+		rdp_out_newpointer_caps(s);
+	}
+	else
+	{
+		rdp_out_bmpcache_caps(s);
+		rdp_out_pointer_caps(s);
+	}
+	rdp_out_colcache_caps(s);
+	rdp_out_activate_caps(s);
+	rdp_out_control_caps(s);
+	rdp_out_share_caps(s);
+	rdp_out_brushcache_caps(s);
+
+	rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d);	/* CAPSTYPE_INPUT */
+	rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);	/* CAPSTYPE_SOUND */
+	rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);	/* CAPSTYPE_FONT */
+	rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10);	/* CAPSTYPE_GLYPHCACHE */
+
+	s_mark_end(s);
+	sec_send(s, sec_flags);
+}
+
+/* Process a general capability set */
+static void
+rdp_process_general_caps(STREAM s)
+{
+	uint16 pad2octetsB;	/* rdp5 flags? */
+
+	in_uint8s(s, 10);
+	in_uint16_le(s, pad2octetsB);
+
+	if (!pad2octetsB)
+		g_rdp_version = RDP_V4;
+}
+
+/* Process a bitmap capability set */
+static void
+rdp_process_bitmap_caps(STREAM s)
+{
+	uint16 width, height, depth;
+
+	in_uint16_le(s, depth);
+	in_uint8s(s, 6);
+
+	in_uint16_le(s, width);
+	in_uint16_le(s, height);
+
+	DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth));
+
+	/*
+	 * The server may limit depth and change the size of the desktop (for
+	 * example when shadowing another session).
+	 */
+	if (g_server_depth != depth)
+	{
+		warning("Remote desktop does not support colour depth %d; falling back to %d\n",
+			g_server_depth, depth);
+		g_server_depth = depth;
+	}
+	if (g_width != width || g_height != height)
+	{
+		warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height,
+			width, height);
+		g_width = width;
+		g_height = height;
+		ui_resize_window();
+	}
+}
+
+/* Process server capabilities */
+static void
+rdp_process_server_caps(STREAM s, uint16 length)
+{
+	int n;
+	uint8 *next, *start;
+	uint16 ncapsets, capset_type, capset_length;
+
+	start = s->p;
+
+	in_uint16_le(s, ncapsets);
+	in_uint8s(s, 2);	/* pad */
+
+	for (n = 0; n < ncapsets; n++)
+	{
+		if (s->p > start + length)
+			return;
+
+		in_uint16_le(s, capset_type);
+		in_uint16_le(s, capset_length);
+
+		next = s->p + capset_length - 4;
+
+		switch (capset_type)
+		{
+			case RDP_CAPSET_GENERAL:
+				rdp_process_general_caps(s);
+				break;
+
+			case RDP_CAPSET_BITMAP:
+				rdp_process_bitmap_caps(s);
+				break;
+		}
+
+		s->p = next;
+	}
+}
+
+/* Respond to a demand active PDU */
+static void
+process_demand_active(STREAM s)
+{
+	uint8 type;
+	uint16 len_src_descriptor, len_combined_caps;
+
+	/* at this point we need to ensure that we have ui created */
+	rd_create_ui();
+
+	in_uint32_le(s, g_rdp_shareid);
+	in_uint16_le(s, len_src_descriptor);
+	in_uint16_le(s, len_combined_caps);
+	in_uint8s(s, len_src_descriptor);
+
+	DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
+	rdp_process_server_caps(s, len_combined_caps);
+
+	rdp_send_confirm_active();
+	rdp_send_synchronise();
+	rdp_send_control(RDP_CTL_COOPERATE);
+	rdp_send_control(RDP_CTL_REQUEST_CONTROL);
+	rdp_recv(&type);	/* RDP_PDU_SYNCHRONIZE */
+	rdp_recv(&type);	/* RDP_CTL_COOPERATE */
+	rdp_recv(&type);	/* RDP_CTL_GRANT_CONTROL */
+	rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
+		       g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0);
+
+	if (g_rdp_version >= RDP_V5)
+	{
+		rdp_enum_bmpcache2();
+		rdp_send_fonts(3);
+	}
+	else
+	{
+		rdp_send_fonts(1);
+		rdp_send_fonts(2);
+	}
+
+	rdp_recv(&type);	/* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
+	reset_order_state();
+}
+
+/* Process a colour pointer PDU */
+static void
+process_colour_pointer_common(STREAM s, int bpp)
+{
+	uint16 width, height, cache_idx, masklen, datalen;
+	uint16 x, y;
+	uint8 *mask;
+	uint8 *data;
+	RD_HCURSOR cursor;
+
+	in_uint16_le(s, cache_idx);
+	in_uint16_le(s, x);
+	in_uint16_le(s, y);
+	in_uint16_le(s, width);
+	in_uint16_le(s, height);
+	in_uint16_le(s, masklen);
+	in_uint16_le(s, datalen);
+	in_uint8p(s, data, datalen);
+	in_uint8p(s, mask, masklen);
+	if ((width != 32) || (height != 32))
+	{
+		warning("process_colour_pointer_common: " "width %d height %d\n", width, height);
+	}
+
+	/* keep hotspot within cursor bounding box */
+	x = MIN(x, width - 1);
+	y = MIN(y, height - 1);
+	cursor = ui_create_cursor(x, y, width, height, mask, data, bpp);
+	ui_set_cursor(cursor);
+	cache_put_cursor(cache_idx, cursor);
+}
+
+/* Process a colour pointer PDU */
+void
+process_colour_pointer_pdu(STREAM s)
+{
+	process_colour_pointer_common(s, 24);
+}
+
+/* Process a New Pointer PDU - these pointers have variable bit depth */
+void
+process_new_pointer_pdu(STREAM s)
+{
+	int xor_bpp;
+
+	in_uint16_le(s, xor_bpp);
+	process_colour_pointer_common(s, xor_bpp);
+}
+
+/* Process a cached pointer PDU */
+void
+process_cached_pointer_pdu(STREAM s)
+{
+	uint16 cache_idx;
+
+	in_uint16_le(s, cache_idx);
+	ui_set_cursor(cache_get_cursor(cache_idx));
+}
+
+/* Process a system pointer PDU */
+void
+process_system_pointer_pdu(STREAM s)
+{
+	uint16 system_pointer_type;
+
+	in_uint16_le(s, system_pointer_type);
+	switch (system_pointer_type)
+	{
+		case RDP_NULL_POINTER:
+			ui_set_null_cursor();
+			break;
+
+		default:
+			unimpl("System pointer message 0x%x\n", system_pointer_type);
+	}
+}
+
+/* Process a pointer PDU */
+static void
+process_pointer_pdu(STREAM s)
+{
+	uint16 message_type;
+	uint16 x, y;
+
+	in_uint16_le(s, message_type);
+	in_uint8s(s, 2);	/* pad */
+
+	switch (message_type)
+	{
+		case RDP_POINTER_MOVE:
+			in_uint16_le(s, x);
+			in_uint16_le(s, y);
+			if (s_check(s))
+				ui_move_pointer(x, y);
+			break;
+
+		case RDP_POINTER_COLOR:
+			process_colour_pointer_pdu(s);
+			break;
+
+		case RDP_POINTER_CACHED:
+			process_cached_pointer_pdu(s);
+			break;
+
+		case RDP_POINTER_SYSTEM:
+			process_system_pointer_pdu(s);
+			break;
+
+		case RDP_POINTER_NEW:
+			process_new_pointer_pdu(s);
+			break;
+
+		default:
+			unimpl("Pointer message 0x%x\n", message_type);
+	}
+}
+
+/* Process bitmap updates */
+void
+process_bitmap_updates(STREAM s)
+{
+	uint16 num_updates;
+	uint16 left, top, right, bottom, width, height;
+	uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
+	uint8 *data, *bmpdata;
+	int i;
+
+	in_uint16_le(s, num_updates);
+
+	for (i = 0; i < num_updates; i++)
+	{
+		in_uint16_le(s, left);
+		in_uint16_le(s, top);
+		in_uint16_le(s, right);
+		in_uint16_le(s, bottom);
+		in_uint16_le(s, width);
+		in_uint16_le(s, height);
+		in_uint16_le(s, bpp);
+		Bpp = (bpp + 7) / 8;
+		in_uint16_le(s, compress);
+		in_uint16_le(s, bufsize);
+
+		cx = right - left + 1;
+		cy = bottom - top + 1;
+
+		DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
+		       left, top, right, bottom, width, height, Bpp, compress));
+
+		if (!compress)
+		{
+			int y;
+			bmpdata = (uint8 *) xmalloc(width * height * Bpp);
+			for (y = 0; y < height; y++)
+			{
+				in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
+					  width * Bpp);
+			}
+			ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
+			xfree(bmpdata);
+			continue;
+		}
+
+
+		if (compress & 0x400)
+		{
+			size = bufsize;
+		}
+		else
+		{
+			in_uint8s(s, 2);	/* pad */
+			in_uint16_le(s, size);
+			in_uint8s(s, 4);	/* line_size, final_size */
+		}
+		in_uint8p(s, data, size);
+		bmpdata = (uint8 *) xmalloc(width * height * Bpp);
+		if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
+		{
+			ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
+		}
+		else
+		{
+			DEBUG_RDP5(("Failed to decompress data\n"));
+		}
+
+		xfree(bmpdata);
+	}
+}
+
+/* Process a palette update */
+void
+process_palette(STREAM s)
+{
+	COLOURENTRY *entry;
+	COLOURMAP map;
+	RD_HCOLOURMAP hmap;
+	int i;
+
+	in_uint8s(s, 2);	/* pad */
+	in_uint16_le(s, map.ncolours);
+	in_uint8s(s, 2);	/* pad */
+
+	map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
+
+	DEBUG(("PALETTE(c=%d)\n", map.ncolours));
+
+	for (i = 0; i < map.ncolours; i++)
+	{
+		entry = &map.colours[i];
+		in_uint8(s, entry->red);
+		in_uint8(s, entry->green);
+		in_uint8(s, entry->blue);
+	}
+
+	hmap = ui_create_colourmap(&map);
+	ui_set_colourmap(hmap);
+
+	xfree(map.colours);
+}
+
+/* Process an update PDU */
+static void
+process_update_pdu(STREAM s)
+{
+	uint16 update_type, count;
+
+	in_uint16_le(s, update_type);
+
+	ui_begin_update();
+	switch (update_type)
+	{
+		case RDP_UPDATE_ORDERS:
+			in_uint8s(s, 2);	/* pad */
+			in_uint16_le(s, count);
+			in_uint8s(s, 2);	/* pad */
+			process_orders(s, count);
+			break;
+
+		case RDP_UPDATE_BITMAP:
+			process_bitmap_updates(s);
+			break;
+
+		case RDP_UPDATE_PALETTE:
+			process_palette(s);
+			break;
+
+		case RDP_UPDATE_SYNCHRONIZE:
+			break;
+
+		default:
+			unimpl("update %d\n", update_type);
+	}
+	ui_end_update();
+}
+
+
+/* Process a Save Session Info PDU */
+void
+process_pdu_logon(STREAM s)
+{
+	uint32 infotype;
+	in_uint32_le(s, infotype);
+	if (infotype == INFOTYPE_LOGON_EXTENDED_INF)
+	{
+		uint32 fieldspresent;
+
+		in_uint8s(s, 2);	/* Length */
+		in_uint32_le(s, fieldspresent);
+		if (fieldspresent & LOGON_EX_AUTORECONNECTCOOKIE)
+		{
+			uint32 len;
+			uint32 version;
+
+			/* TS_LOGON_INFO_FIELD */
+			in_uint8s(s, 4);	/* cbFieldData */
+
+			/* ARC_SC_PRIVATE_PACKET */
+			in_uint32_le(s, len);
+			if (len != 28)
+			{
+				warning("Invalid length in Auto-Reconnect packet\n");
+				return;
+			}
+
+			in_uint32_le(s, version);
+			if (version != 1)
+			{
+				warning("Unsupported version of Auto-Reconnect packet\n");
+				return;
+			}
+
+			in_uint32_le(s, g_reconnect_logonid);
+			in_uint8a(s, g_reconnect_random, 16);
+			g_has_reconnect_random = True;
+			g_reconnect_random_ts = time(NULL);
+			DEBUG(("Saving auto-reconnect cookie, id=%u\n", g_reconnect_logonid));
+		}
+	}
+}
+
+
+/* Process a disconnect PDU */
+void
+process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
+{
+	in_uint32_le(s, *ext_disc_reason);
+
+	DEBUG(("Received disconnect PDU\n"));
+}
+
+/* Process data PDU */
+static RD_BOOL
+process_data_pdu(STREAM s, uint32 * ext_disc_reason)
+{
+	uint8 data_pdu_type;
+	uint8 ctype;
+	uint16 clen;
+	uint32 len;
+
+	uint32 roff, rlen;
+
+	struct stream *ns = &(g_mppc_dict.ns);
+
+	in_uint8s(s, 6);	/* shareid, pad, streamid */
+	in_uint16_le(s, len);
+	in_uint8(s, data_pdu_type);
+	in_uint8(s, ctype);
+	in_uint16_le(s, clen);
+	clen -= 18;
+
+	if (ctype & RDP_MPPC_COMPRESSED)
+	{
+		if (len > RDP_MPPC_DICT_SIZE)
+			error("error decompressed packet size exceeds max\n");
+		if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
+			error("error while decompressing packet\n");
+
+		/* len -= 18; */
+
+		/* allocate memory and copy the uncompressed data into the temporary stream */
+		ns->data = (uint8 *) xrealloc(ns->data, rlen);
+
+		memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
+
+		ns->size = rlen;
+		ns->end = (ns->data + ns->size);
+		ns->p = ns->data;
+		ns->rdp_hdr = ns->p;
+
+		s = ns;
+	}
+
+	switch (data_pdu_type)
+	{
+		case RDP_DATA_PDU_UPDATE:
+			process_update_pdu(s);
+			break;
+
+		case RDP_DATA_PDU_CONTROL:
+			DEBUG(("Received Control PDU\n"));
+			break;
+
+		case RDP_DATA_PDU_SYNCHRONISE:
+			DEBUG(("Received Sync PDU\n"));
+			break;
+
+		case RDP_DATA_PDU_POINTER:
+			process_pointer_pdu(s);
+			break;
+
+		case RDP_DATA_PDU_BELL:
+			ui_bell();
+			break;
+
+		case RDP_DATA_PDU_LOGON:
+			DEBUG(("Received Logon PDU\n"));
+			/* User logged on */
+			process_pdu_logon(s);
+			break;
+
+		case RDP_DATA_PDU_DISCONNECT:
+			process_disconnect_pdu(s, ext_disc_reason);
+
+			/* We used to return true and disconnect immediately here, but
+			 * Windows Vista sends a disconnect PDU with reason 0 when
+			 * reconnecting to a disconnected session, and MSTSC doesn't
+			 * drop the connection.  I think we should just save the status.
+			 */
+			break;
+
+		case RDP_DATA_PDU_AUTORECONNECT_STATUS:
+			warning("Automatic reconnect using cookie, failed.\n");
+			break;
+
+		default:
+			unimpl("data PDU %d\n", data_pdu_type);
+	}
+	return False;
+}
+
+/* Process redirect PDU from Session Directory */
+static RD_BOOL
+process_redirect_pdu(STREAM s, RD_BOOL enhanced_redirect /*, uint32 * ext_disc_reason */ )
+{
+	uint32 len;
+	uint16 redirect_identifier;
+
+	/* reset any previous redirection information */
+	g_redirect = True;
+	free(g_redirect_server);
+	free(g_redirect_username);
+	free(g_redirect_domain);
+	free(g_redirect_lb_info);
+	free(g_redirect_cookie);
+
+	g_redirect_server = NULL;
+	g_redirect_username = NULL;
+	g_redirect_domain = NULL;
+	g_redirect_lb_info = NULL;
+	g_redirect_cookie = NULL;
+
+	/* these 2 bytes are unknown, seem to be zeros */
+	in_uint8s(s, 2);
+
+	/* FIXME: Previous implementation only reads 4 bytes which has been working
+	   but todays spec says something different. Investigate and retest
+	   server redirection using WTS 2003 cluster.
+	 */
+
+	if (enhanced_redirect)
+	{
+		/* read identifier */
+		in_uint16_le(s, redirect_identifier);
+		if (redirect_identifier != 0x0400)
+			error("Protocol error in server redirection, unexpected data.");
+
+		/* FIXME: skip total length */
+		in_uint8s(s, 2);
+
+		/* read session_id */
+		in_uint32_le(s, g_redirect_session_id);
+	}
+
+	/* read connection flags */
+	in_uint32_le(s, g_redirect_flags);
+
+	if (g_redirect_flags & PDU_REDIRECT_HAS_IP)
+	{
+		/* read length of ip string */
+		in_uint32_le(s, len);
+
+		/* read ip string */
+		rdp_in_unistr(s, len, &g_redirect_server, &g_redirect_server_len);
+	}
+
+	if (g_redirect_flags & PDU_REDIRECT_HAS_LOAD_BALANCE_INFO)
+	{
+		/* read length of load balance info blob */
+		in_uint32_le(s, g_redirect_lb_info_len);
+
+		/* reallocate a loadbalance info blob */
+		if (g_redirect_lb_info != NULL)
+			free(g_redirect_lb_info);
+
+		g_redirect_lb_info = xmalloc(g_redirect_lb_info_len);
+
+		/* read load balance info blob */
+		in_uint8p(s, g_redirect_lb_info, g_redirect_lb_info_len);
+	}
+
+	if (g_redirect_flags & PDU_REDIRECT_HAS_USERNAME)
+	{
+		/* read length of username string */
+		in_uint32_le(s, len);
+
+		/* read username string */
+		rdp_in_unistr(s, len, &g_redirect_username, &g_redirect_username_len);
+	}
+
+	if (g_redirect_flags & PDU_REDIRECT_HAS_DOMAIN)
+	{
+		/* read length of domain string */
+		in_uint32_le(s, len);
+
+		/* read domain string */
+		rdp_in_unistr(s, len, &g_redirect_domain, &g_redirect_domain_len);
+	}
+
+	if (g_redirect_flags & PDU_REDIRECT_HAS_PASSWORD)
+	{
+		/* the information in this blob is either a password or a cookie that
+		   should be passed though as blob and not parsed as a unicode string */
+
+		/* read blob length */
+		in_uint32_le(s, g_redirect_cookie_len);
+
+		/* reallocate cookie blob */
+		if (g_redirect_cookie != NULL)
+			free(g_redirect_cookie);
+
+		g_redirect_cookie = xmalloc(g_redirect_cookie_len);
+
+		/* read cookie as is */
+		in_uint8p(s, g_redirect_cookie, g_redirect_cookie_len);
+	}
+
+	if (g_redirect_flags & PDU_REDIRECT_DONT_STORE_USERNAME)
+	{
+		warning("PDU_REDIRECT_DONT_STORE_USERNAME set\n");
+	}
+
+	if (g_redirect_flags & PDU_REDIRECT_USE_SMARTCARD)
+	{
+		warning("PDU_REDIRECT_USE_SMARTCARD set\n");
+	}
+
+	if (g_redirect_flags & PDU_REDIRECT_INFORMATIONAL)
+	{
+		/* By spec this is only for information and doesn't mean that an actual
+		   redirect should be performed. How it should be used is not mentioned. */
+		g_redirect = False;
+	}
+
+	if (g_redirect_flags & PDU_REDIRECT_HAS_TARGET_FQDN)
+	{
+		in_uint32_le(s, len);
+
+		/* Let target fqdn replace target ip address */
+		if (g_redirect_server)
+		{
+			free(g_redirect_server);
+			g_redirect_server = NULL;
+		}
+
+		/* read fqdn string */
+		rdp_in_unistr(s, len, &g_redirect_server, &g_redirect_server_len);
+	}
+
+	if (g_redirect_flags & PDU_REDIRECT_HAS_TARGET_NETBIOS)
+	{
+		warning("PDU_REDIRECT_HAS_TARGET_NETBIOS set\n");
+	}
+
+	if (g_redirect_flags & PDU_REDIRECT_HAS_TARGET_IP_ARRAY)
+	{
+		warning("PDU_REDIRECT_HAS_TARGET_IP_ARRAY set\n");
+	}
+
+	return True;
+}
+
+/* Process incoming packets */
+void
+rdp_main_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
+{
+	while (rdp_loop(deactivated, ext_disc_reason))
+	{
+		if (g_pending_resize || g_redirect)
+		{
+			return;
+		}
+	}
+}
+
+/* used in uiports and rdp_main_loop, processes the rdp packets waiting */
+RD_BOOL
+rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
+{
+	uint8 type;
+	RD_BOOL cont = True;
+	STREAM s;
+
+	while (cont)
+	{
+		s = rdp_recv(&type);
+		if (s == NULL)
+			return False;
+		switch (type)
+		{
+			case RDP_PDU_DEMAND_ACTIVE:
+				process_demand_active(s);
+				*deactivated = False;
+				break;
+			case RDP_PDU_DEACTIVATE:
+				DEBUG(("RDP_PDU_DEACTIVATE\n"));
+				*deactivated = True;
+				break;
+			case RDP_PDU_REDIRECT:
+				return process_redirect_pdu(s, False);
+				break;
+			case RDP_PDU_ENHANCED_REDIRECT:
+				return process_redirect_pdu(s, True);
+				break;
+			case RDP_PDU_DATA:
+				/* If we got a data PDU, we don't need to keep the password in memory
+				   anymore and therefor we should clear it for security reasons. */
+				if (g_password[0] != '\0')
+					memset(g_password, 0, sizeof(g_password));
+
+				process_data_pdu(s, ext_disc_reason);
+				break;
+			case 0:
+				break;
+			default:
+				unimpl("PDU %d\n", type);
+		}
+		cont = g_next_packet < s->end;
+	}
+	return True;
+}
+
+/* Establish a connection up to the RDP layer */
+RD_BOOL
+rdp_connect(char *server, uint32 flags, char *domain, char *password,
+	    char *command, char *directory, RD_BOOL reconnect)
+{
+	RD_BOOL deactivated = False;
+	uint32 ext_disc_reason = 0;
+
+	if (!sec_connect(server, g_username, domain, password, reconnect))
+		return False;
+
+	rdp_send_logon_info(flags, domain, g_username, password, command, directory);
+
+	/* run RDP loop until first licence demand active PDU */
+	while (!g_rdp_shareid)
+	{
+		if (g_network_error)
+			return False;
+
+		if (!rdp_loop(&deactivated, &ext_disc_reason))
+			return False;
+
+		if (g_redirect)
+			return True;
+	}
+	return True;
+}
+
+/* Called during redirection to reset the state to support redirection */
+void
+rdp_reset_state(void)
+{
+	g_next_packet = NULL;	/* reset the packet information */
+	g_rdp_shareid = 0;
+	sec_reset_state();
+}
+
+/* Disconnect from the RDP layer */
+void
+rdp_disconnect(void)
+{
+	sec_disconnect();
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/rdp5.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdp5.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdp5.c	(revision 55121)
@@ -0,0 +1,123 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - RDP5 short form PDU processing
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright 2003-2008 Erik Forsberg <forsberg@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+
+extern uint8 *g_next_packet;
+
+extern RDPCOMP g_mppc_dict;
+
+void
+rdp5_process(STREAM s)
+{
+	uint16 length, count, x, y;
+	uint8 type, ctype;
+	uint8 *next;
+
+	uint32 roff, rlen;
+	struct stream *ns = &(g_mppc_dict.ns);
+	struct stream *ts;
+
+#if 0
+	printf("RDP5 data:\n");
+	hexdump(s->p, s->end - s->p);
+#endif
+
+	ui_begin_update();
+	while (s->p < s->end)
+	{
+		in_uint8(s, type);
+		if (type & RDP5_COMPRESSED)
+		{
+			in_uint8(s, ctype);
+			in_uint16_le(s, length);
+			type ^= RDP5_COMPRESSED;
+		}
+		else
+		{
+			ctype = 0;
+			in_uint16_le(s, length);
+		}
+		g_next_packet = next = s->p + length;
+
+		if (ctype & RDP_MPPC_COMPRESSED)
+		{
+			if (mppc_expand(s->p, length, ctype, &roff, &rlen) == -1)
+				error("error while decompressing packet\n");
+
+			/* allocate memory and copy the uncompressed data into the temporary stream */
+			ns->data = (uint8 *) xrealloc(ns->data, rlen);
+
+			memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
+
+			ns->size = rlen;
+			ns->end = (ns->data + ns->size);
+			ns->p = ns->data;
+			ns->rdp_hdr = ns->p;
+
+			ts = ns;
+		}
+		else
+			ts = s;
+
+		switch (type)
+		{
+			case 0:	/* update orders */
+				in_uint16_le(ts, count);
+				process_orders(ts, count);
+				break;
+			case 1:	/* update bitmap */
+				in_uint8s(ts, 2);	/* part length */
+				process_bitmap_updates(ts);
+				break;
+			case 2:	/* update palette */
+				in_uint8s(ts, 2);	/* uint16 = 2 */
+				process_palette(ts);
+				break;
+			case 3:	/* update synchronize */
+				break;
+			case 5:	/* null pointer */
+				ui_set_null_cursor();
+				break;
+			case 6:	/* default pointer */
+				break;
+			case 8:	/* pointer position */
+				in_uint16_le(ts, x);
+				in_uint16_le(ts, y);
+				if (s_check(ts))
+					ui_move_pointer(x, y);
+				break;
+			case 9:	/* color pointer */
+				process_colour_pointer_pdu(ts);
+				break;
+			case 10:	/* cached pointer */
+				process_cached_pointer_pdu(ts);
+				break;
+			case 11:
+				process_new_pointer_pdu(ts);
+				break;
+			default:
+				unimpl("RDP5 opcode %d\n", type);
+		}
+
+		s->p = next;
+	}
+	ui_end_update();
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/rdpdr.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdpdr.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdpdr.c	(revision 55121)
@@ -0,0 +1,1240 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright 2004-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+   Copyright 2010-2014 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+  Here are some resources, for your IRP hacking pleasure:
+
+  http://cvs.sourceforge.net/viewcvs.py/mingw/w32api/include/ddk/winddk.h?view=markup
+
+  http://win32.mvps.org/ntfs/streams.cpp
+
+  http://www.acc.umu.se/~bosse/ntifs.h
+
+  http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/
+
+  http://us1.samba.org/samba/ftp/specs/smb-nt01.txt
+
+  http://www.osronline.com/
+*/
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <dirent.h>		/* opendir, closedir, readdir */
+#include <time.h>
+#include <errno.h>
+#include "rdesktop.h"
+
+#define IRP_MJ_CREATE			0x00
+#define IRP_MJ_CLOSE			0x02
+#define IRP_MJ_READ			0x03
+#define IRP_MJ_WRITE			0x04
+#define	IRP_MJ_QUERY_INFORMATION	0x05
+#define IRP_MJ_SET_INFORMATION		0x06
+#define IRP_MJ_QUERY_VOLUME_INFORMATION	0x0a
+#define IRP_MJ_DIRECTORY_CONTROL	0x0c
+#define IRP_MJ_DEVICE_CONTROL		0x0e
+#define IRP_MJ_LOCK_CONTROL             0x11
+
+#define IRP_MN_QUERY_DIRECTORY          0x01
+#define IRP_MN_NOTIFY_CHANGE_DIRECTORY  0x02
+
+extern char g_hostname[16];
+extern DEVICE_FNS serial_fns;
+extern DEVICE_FNS printer_fns;
+extern DEVICE_FNS parallel_fns;
+extern DEVICE_FNS disk_fns;
+#ifdef WITH_SCARD
+extern DEVICE_FNS scard_fns;
+#endif
+extern FILEINFO g_fileinfo[];
+extern RD_BOOL g_notify_stamp;
+
+static VCHANNEL *rdpdr_channel;
+static uint32 g_epoch;
+
+/* If select() times out, the request for the device with handle g_min_timeout_fd is aborted */
+RD_NTHANDLE g_min_timeout_fd;
+uint32 g_num_devices;
+
+uint32 g_client_id;
+
+/* Table with information about rdpdr devices */
+RDPDR_DEVICE g_rdpdr_device[RDPDR_MAX_DEVICES];
+char *g_rdpdr_clientname = NULL;
+
+/* Used to store incoming io request, until they are ready to be completed */
+/* using a linked list ensures that they are processed in the right order, */
+/* if multiple ios are being done on the same fd */
+struct async_iorequest
+{
+	uint32 fd, major, minor, offset, device, id, length, partial_len;
+	long timeout,		/* Total timeout */
+	  itv_timeout;		/* Interval timeout (between serial characters) */
+	uint8 *buffer;
+	DEVICE_FNS *fns;
+
+	struct async_iorequest *next;	/* next element in list */
+};
+
+struct async_iorequest *g_iorequest;
+
+/* Return device_id for a given handle */
+int
+get_device_index(RD_NTHANDLE handle)
+{
+	int i;
+	for (i = 0; i < RDPDR_MAX_DEVICES; i++)
+	{
+		if (g_rdpdr_device[i].handle == handle)
+			return i;
+	}
+	return -1;
+}
+
+/* Converts a windows path to a unix path */
+void
+convert_to_unix_filename(char *filename)
+{
+	char *p;
+
+	while ((p = strchr(filename, '\\')))
+	{
+		*p = '/';
+	}
+}
+
+static RD_BOOL
+rdpdr_handle_ok(int device, int handle)
+{
+	switch (g_rdpdr_device[device].device_type)
+	{
+		case DEVICE_TYPE_PARALLEL:
+		case DEVICE_TYPE_SERIAL:
+		case DEVICE_TYPE_PRINTER:
+		case DEVICE_TYPE_SCARD:
+			if (g_rdpdr_device[device].handle != handle)
+				return False;
+			break;
+		case DEVICE_TYPE_DISK:
+			if (g_fileinfo[handle].device_id != device)
+				return False;
+			break;
+	}
+	return True;
+}
+
+/* Add a new io request to the table containing pending io requests so it won't block rdesktop */
+static RD_BOOL
+add_async_iorequest(uint32 device, uint32 file, uint32 id, uint32 major, uint32 length,
+		    DEVICE_FNS * fns, uint32 total_timeout, uint32 interval_timeout, uint8 * buffer,
+		    uint32 offset)
+{
+	struct async_iorequest *iorq;
+
+	if (g_iorequest == NULL)
+	{
+		g_iorequest = (struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
+		if (!g_iorequest)
+			return False;
+		g_iorequest->fd = 0;
+		g_iorequest->next = NULL;
+	}
+
+	iorq = g_iorequest;
+
+	while (iorq->fd != 0)
+	{
+		/* create new element if needed */
+		if (iorq->next == NULL)
+		{
+			iorq->next =
+				(struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
+			if (!iorq->next)
+				return False;
+			iorq->next->fd = 0;
+			iorq->next->next = NULL;
+		}
+		iorq = iorq->next;
+	}
+	iorq->device = device;
+	iorq->fd = file;
+	iorq->id = id;
+	iorq->major = major;
+	iorq->length = length;
+	iorq->partial_len = 0;
+	iorq->fns = fns;
+	iorq->timeout = total_timeout;
+	iorq->itv_timeout = interval_timeout;
+	iorq->buffer = buffer;
+	iorq->offset = offset;
+	return True;
+}
+
+static void
+rdpdr_send_client_announce_reply(void)
+{
+	/* DR_CORE_CLIENT_ANNOUNCE_RSP */
+	STREAM s;
+	s = channel_init(rdpdr_channel, 12);
+	out_uint16_le(s, RDPDR_CTYP_CORE);
+	out_uint16_le(s, PAKID_CORE_CLIENTID_CONFIRM);
+	out_uint16_le(s, 1);	/* VersionMajor, MUST be set to 0x1 */
+	out_uint16_le(s, 5);	/* VersionMinor */
+	out_uint32_be(s, g_client_id);	/* ClientID */
+	s_mark_end(s);
+	channel_send(s, rdpdr_channel);
+}
+
+
+static void
+rdpdr_send_client_name_request(void)
+{
+	/* DR_CORE_CLIENT_NAME_REQ */
+	STREAM s;
+	uint32 hostlen;
+
+	if (NULL == g_rdpdr_clientname)
+	{
+		g_rdpdr_clientname = g_hostname;
+	}
+	hostlen = (strlen(g_rdpdr_clientname) + 1) * 2;
+
+	s = channel_init(rdpdr_channel, 16 + hostlen);
+	out_uint16_le(s, RDPDR_CTYP_CORE);
+	out_uint16_le(s, PAKID_CORE_CLIENT_NAME);
+	out_uint32_le(s, 1);	/* UnicodeFlag */
+	out_uint32_le(s, 0);	/* CodePage */
+	out_uint32_le(s, hostlen);	/* ComputerNameLen */
+	rdp_out_unistr(s, g_rdpdr_clientname, hostlen - 2);
+	s_mark_end(s);
+	channel_send(s, rdpdr_channel);
+}
+
+/* Returns the size of the payload of the announce packet */
+static int
+announcedata_size()
+{
+	int size, i;
+	PRINTER *printerinfo;
+
+	size = 8;		/* static announce size */
+	size += g_num_devices * 0x14;
+
+	for (i = 0; i < g_num_devices; i++)
+	{
+		if (g_rdpdr_device[i].device_type == DEVICE_TYPE_PRINTER)
+		{
+			printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;
+			printerinfo->bloblen =
+				printercache_load_blob(printerinfo->printer, &(printerinfo->blob));
+
+			size += 0x18;
+			size += 2 * strlen(printerinfo->driver) + 2;
+			size += 2 * strlen(printerinfo->printer) + 2;
+			size += printerinfo->bloblen;
+		}
+	}
+
+	return size;
+}
+
+static void
+rdpdr_send_client_device_list_announce(void)
+{
+	/* DR_CORE_CLIENT_ANNOUNCE_RSP */
+	uint32 driverlen, printerlen, bloblen;
+	int i;
+	STREAM s;
+	PRINTER *printerinfo;
+
+	s = channel_init(rdpdr_channel, announcedata_size());
+	out_uint16_le(s, RDPDR_CTYP_CORE);
+	out_uint16_le(s, PAKID_CORE_DEVICE_LIST_ANNOUNCE);
+
+	out_uint32_le(s, g_num_devices);
+
+	for (i = 0; i < g_num_devices; i++)
+	{
+		out_uint32_le(s, g_rdpdr_device[i].device_type);
+		out_uint32_le(s, i);	/* RDP Device ID */
+		/* Is it possible to use share names longer than 8 chars?
+		   /astrand */
+		out_uint8p(s, g_rdpdr_device[i].name, 8);
+
+		switch (g_rdpdr_device[i].device_type)
+		{
+			case DEVICE_TYPE_PRINTER:
+				printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;
+
+				driverlen = 2 * strlen(printerinfo->driver) + 2;
+				printerlen = 2 * strlen(printerinfo->printer) + 2;
+				bloblen = printerinfo->bloblen;
+
+				out_uint32_le(s, 24 + driverlen + printerlen + bloblen);	/* length of extra info */
+				out_uint32_le(s, printerinfo->default_printer ? 2 : 0);
+				out_uint8s(s, 8);	/* unknown */
+				out_uint32_le(s, driverlen);
+				out_uint32_le(s, printerlen);
+				out_uint32_le(s, bloblen);
+				rdp_out_unistr(s, printerinfo->driver, driverlen - 2);
+				rdp_out_unistr(s, printerinfo->printer, printerlen - 2);
+				out_uint8a(s, printerinfo->blob, bloblen);
+
+				if (printerinfo->blob)
+					xfree(printerinfo->blob);	/* Blob is sent twice if reconnecting */
+				break;
+			default:
+				out_uint32(s, 0);
+		}
+	}
+
+	s_mark_end(s);
+	channel_send(s, rdpdr_channel);
+}
+
+void
+rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,
+		      uint32 length)
+{
+	STREAM s;
+
+#ifdef WITH_SCARD
+	scard_lock(SCARD_LOCK_RDPDR);
+#endif
+	s = channel_init(rdpdr_channel, 20 + length);
+	out_uint16_le(s, RDPDR_CTYP_CORE);
+	out_uint16_le(s, PAKID_CORE_DEVICE_IOCOMPLETION);
+	out_uint32_le(s, device);
+	out_uint32_le(s, id);
+	out_uint32_le(s, status);
+	out_uint32_le(s, result);
+	out_uint8p(s, buffer, length);
+	s_mark_end(s);
+	/* JIF */
+#ifdef WITH_DEBUG_RDP5
+	printf("--> rdpdr_send_completion\n");
+	/* hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
+#endif
+	channel_send(s, rdpdr_channel);
+#ifdef WITH_SCARD
+	scard_unlock(SCARD_LOCK_RDPDR);
+#endif
+}
+
+static void
+rdpdr_process_irp(STREAM s)
+{
+	uint32 result = 0,
+		length = 0,
+		desired_access = 0,
+		request,
+		file,
+		info_level,
+		buffer_len,
+		id,
+		major,
+		minor,
+		device,
+		offset,
+		bytes_in,
+		bytes_out,
+		error_mode,
+		share_mode, disposition, total_timeout, interval_timeout, flags_and_attributes = 0;
+
+	char *filename;
+	uint32 filename_len;
+
+	uint8 *buffer, *pst_buf;
+	struct stream out;
+	DEVICE_FNS *fns;
+	RD_BOOL rw_blocking = True;
+	RD_NTSTATUS status = RD_STATUS_INVALID_DEVICE_REQUEST;
+
+	in_uint32_le(s, device);
+	in_uint32_le(s, file);
+	in_uint32_le(s, id);
+	in_uint32_le(s, major);
+	in_uint32_le(s, minor);
+
+	filename = NULL;
+
+	buffer_len = 0;
+	buffer = (uint8 *) xmalloc(1024);
+	buffer[0] = 0;
+
+	if (device >= RDPDR_MAX_DEVICES)
+	{
+		error("invalid irp device 0x%lx file 0x%lx id 0x%lx major 0x%lx minor 0x%lx\n",
+		      device, file, id, major, minor);
+		xfree(buffer);
+		return;
+	}
+
+	switch (g_rdpdr_device[device].device_type)
+	{
+		case DEVICE_TYPE_SERIAL:
+
+			fns = &serial_fns;
+			rw_blocking = False;
+			break;
+
+		case DEVICE_TYPE_PARALLEL:
+
+			fns = &parallel_fns;
+			rw_blocking = False;
+			break;
+
+		case DEVICE_TYPE_PRINTER:
+
+			fns = &printer_fns;
+			break;
+
+		case DEVICE_TYPE_DISK:
+
+			fns = &disk_fns;
+			rw_blocking = False;
+			break;
+
+		case DEVICE_TYPE_SCARD:
+#ifdef WITH_SCARD
+			fns = &scard_fns;
+			rw_blocking = False;
+			break;
+#endif
+		default:
+
+			error("IRP for bad device %ld\n", device);
+			xfree(buffer);
+			return;
+	}
+
+	switch (major)
+	{
+		case IRP_MJ_CREATE:
+
+			in_uint32_be(s, desired_access);
+			in_uint8s(s, 0x08);	/* unknown */
+			in_uint32_le(s, error_mode);
+			in_uint32_le(s, share_mode);
+			in_uint32_le(s, disposition);
+			in_uint32_le(s, flags_and_attributes);
+			in_uint32_le(s, length);
+
+			if (length && (length / 2) < 256)
+			{
+				rdp_in_unistr(s, length, &filename, &filename_len);
+				if (filename)
+					convert_to_unix_filename(filename);
+			}
+
+			if (!fns->create)
+			{
+				status = RD_STATUS_NOT_SUPPORTED;
+				free(filename);
+				break;
+			}
+
+			status = fns->create(device, desired_access, share_mode, disposition,
+					     flags_and_attributes, filename, &result);
+
+			free(filename);
+			buffer_len = 1;
+			break;
+
+		case IRP_MJ_CLOSE:
+			if (!fns->close)
+			{
+				status = RD_STATUS_NOT_SUPPORTED;
+				break;
+			}
+
+			status = fns->close(file);
+			break;
+
+		case IRP_MJ_READ:
+
+			if (!fns->read)
+			{
+				status = RD_STATUS_NOT_SUPPORTED;
+				break;
+			}
+
+			in_uint32_le(s, length);
+			in_uint32_le(s, offset);
+#if WITH_DEBUG_RDP5
+			DEBUG(("RDPDR IRP Read (length: %d, offset: %d)\n", length, offset));
+#endif
+			if (!rdpdr_handle_ok(device, file))
+			{
+				status = RD_STATUS_INVALID_HANDLE;
+				break;
+			}
+
+			if (rw_blocking)	/* Complete read immediately */
+			{
+				buffer = (uint8 *) xrealloc((void *) buffer, length);
+				if (!buffer)
+				{
+					status = RD_STATUS_CANCELLED;
+					break;
+				}
+				status = fns->read(file, buffer, length, offset, &result);
+				buffer_len = result;
+				break;
+			}
+
+			/* Add request to table */
+			pst_buf = (uint8 *) xmalloc(length);
+			if (!pst_buf)
+			{
+				status = RD_STATUS_CANCELLED;
+				break;
+			}
+			serial_get_timeout(file, length, &total_timeout, &interval_timeout);
+			if (add_async_iorequest
+			    (device, file, id, major, length, fns, total_timeout, interval_timeout,
+			     pst_buf, offset))
+			{
+				status = RD_STATUS_PENDING;
+				break;
+			}
+
+			status = RD_STATUS_CANCELLED;
+			break;
+		case IRP_MJ_WRITE:
+
+			buffer_len = 1;
+
+			if (!fns->write)
+			{
+				status = RD_STATUS_NOT_SUPPORTED;
+				break;
+			}
+
+			in_uint32_le(s, length);
+			in_uint32_le(s, offset);
+			in_uint8s(s, 0x18);
+#if WITH_DEBUG_RDP5
+			DEBUG(("RDPDR IRP Write (length: %d)\n", result));
+#endif
+			if (!rdpdr_handle_ok(device, file))
+			{
+				status = RD_STATUS_INVALID_HANDLE;
+				break;
+			}
+
+			if (rw_blocking)	/* Complete immediately */
+			{
+				status = fns->write(file, s->p, length, offset, &result);
+				break;
+			}
+
+			/* Add to table */
+			pst_buf = (uint8 *) xmalloc(length);
+			if (!pst_buf)
+			{
+				status = RD_STATUS_CANCELLED;
+				break;
+			}
+
+			in_uint8a(s, pst_buf, length);
+
+			if (add_async_iorequest
+			    (device, file, id, major, length, fns, 0, 0, pst_buf, offset))
+			{
+				status = RD_STATUS_PENDING;
+				break;
+			}
+
+			status = RD_STATUS_CANCELLED;
+			break;
+
+		case IRP_MJ_QUERY_INFORMATION:
+
+			if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
+			{
+				status = RD_STATUS_INVALID_HANDLE;
+				break;
+			}
+			in_uint32_le(s, info_level);
+
+			out.data = out.p = buffer;
+			out.size = sizeof(buffer);
+			status = disk_query_information(file, info_level, &out);
+			result = buffer_len = out.p - out.data;
+
+			break;
+
+		case IRP_MJ_SET_INFORMATION:
+
+			if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
+			{
+				status = RD_STATUS_INVALID_HANDLE;
+				break;
+			}
+
+			in_uint32_le(s, info_level);
+
+			out.data = out.p = buffer;
+			out.size = sizeof(buffer);
+			status = disk_set_information(file, info_level, s, &out);
+			result = buffer_len = out.p - out.data;
+			break;
+
+		case IRP_MJ_QUERY_VOLUME_INFORMATION:
+
+			if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
+			{
+				status = RD_STATUS_INVALID_HANDLE;
+				break;
+			}
+
+			in_uint32_le(s, info_level);
+
+			out.data = out.p = buffer;
+			out.size = sizeof(buffer);
+			status = disk_query_volume_information(file, info_level, &out);
+			result = buffer_len = out.p - out.data;
+			break;
+
+		case IRP_MJ_DIRECTORY_CONTROL:
+
+			if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
+			{
+				status = RD_STATUS_INVALID_HANDLE;
+				break;
+			}
+
+			switch (minor)
+			{
+				case IRP_MN_QUERY_DIRECTORY:
+
+					in_uint32_le(s, info_level);
+					in_uint8s(s, 1);
+					in_uint32_le(s, length);
+					in_uint8s(s, 0x17);
+					if (length && length < 2 * 255)
+					{
+						rdp_in_unistr(s, length, &filename, &filename_len);
+						if (filename)
+							convert_to_unix_filename(filename);
+					}
+
+					out.data = out.p = buffer;
+					out.size = sizeof(buffer);
+					status = disk_query_directory(file, info_level, filename,
+								      &out);
+					result = buffer_len = out.p - out.data;
+					if (!buffer_len)
+						buffer_len++;
+
+					free(filename);
+					break;
+
+				case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
+
+					/* JIF
+					   unimpl("IRP major=0x%x minor=0x%x: IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", major, minor);  */
+
+					in_uint32_le(s, info_level);	/* notify mask */
+
+					status = disk_create_notify(file, info_level);
+					result = 0;
+
+					if (status == RD_STATUS_PENDING)
+						add_async_iorequest(device, file, id, major, length,
+								    fns, 0, 0, NULL, 0);
+					break;
+
+				default:
+
+					status = RD_STATUS_INVALID_PARAMETER;
+					/* JIF */
+					unimpl("IRP major=0x%x minor=0x%x\n", major, minor);
+			}
+			break;
+
+		case IRP_MJ_DEVICE_CONTROL:
+
+			if (!fns->device_control)
+			{
+				status = RD_STATUS_NOT_SUPPORTED;
+				break;
+			}
+
+			in_uint32_le(s, bytes_out);
+			in_uint32_le(s, bytes_in);
+			in_uint32_le(s, request);
+			in_uint8s(s, 0x14);
+
+			buffer = (uint8 *) xrealloc((void *) buffer, bytes_out + 0x14);
+			if (!buffer)
+			{
+				status = RD_STATUS_CANCELLED;
+				break;
+			}
+
+			out.data = out.p = buffer;
+			out.size = sizeof(buffer);
+
+#ifdef WITH_SCARD
+			scardSetInfo(g_epoch, device, id, bytes_out + 0x14);
+#endif
+			status = fns->device_control(file, request, s, &out);
+			result = buffer_len = out.p - out.data;
+
+			/* Serial SERIAL_WAIT_ON_MASK */
+			if (status == RD_STATUS_PENDING)
+			{
+				if (add_async_iorequest
+				    (device, file, id, major, length, fns, 0, 0, NULL, 0))
+				{
+					status = RD_STATUS_PENDING;
+					break;
+				}
+			}
+#ifdef WITH_SCARD
+			else if (status == (RD_STATUS_PENDING | 0xC0000000))
+				status = RD_STATUS_PENDING;
+#endif
+			break;
+
+
+		case IRP_MJ_LOCK_CONTROL:
+
+			if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
+			{
+				status = RD_STATUS_INVALID_HANDLE;
+				break;
+			}
+
+			in_uint32_le(s, info_level);
+
+			out.data = out.p = buffer;
+			out.size = sizeof(buffer);
+			/* FIXME: Perhaps consider actually *do*
+			   something here :-) */
+			status = RD_STATUS_SUCCESS;
+			result = buffer_len = out.p - out.data;
+			break;
+
+		default:
+			unimpl("IRP major=0x%x minor=0x%x\n", major, minor);
+			break;
+	}
+
+	if (status != RD_STATUS_PENDING)
+	{
+		rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
+	}
+	if (buffer)
+		xfree(buffer);
+	buffer = NULL;
+}
+
+static void
+rdpdr_send_client_capability_response(void)
+{
+	/* DR_CORE_CAPABILITY_RSP */
+	STREAM s;
+	s = channel_init(rdpdr_channel, 0x50);
+	out_uint16_le(s, RDPDR_CTYP_CORE);
+	out_uint16_le(s, PAKID_CORE_CLIENT_CAPABILITY);
+	out_uint32_le(s, 5);	/* count */
+	out_uint16_le(s, 1);	/* first */
+	out_uint16_le(s, 0x28);	/* length */
+	out_uint32_le(s, 1);
+	out_uint32_le(s, 2);
+	out_uint16_le(s, 2);
+	out_uint16_le(s, 5);
+	out_uint16_le(s, 1);
+	out_uint16_le(s, 5);
+	out_uint16_le(s, 0xFFFF);
+	out_uint16_le(s, 0);
+	out_uint32_le(s, 0);
+	out_uint32_le(s, 3);
+	out_uint32_le(s, 0);
+	out_uint32_le(s, 0);
+	out_uint16_le(s, 2);	/* second */
+	out_uint16_le(s, 8);	/* length */
+	out_uint32_le(s, 1);
+	out_uint16_le(s, 3);	/* third */
+	out_uint16_le(s, 8);	/* length */
+	out_uint32_le(s, 1);
+	out_uint16_le(s, 4);	/* fourth */
+	out_uint16_le(s, 8);	/* length */
+	out_uint32_le(s, 1);
+	out_uint16_le(s, 5);	/* fifth */
+	out_uint16_le(s, 8);	/* length */
+	out_uint32_le(s, 1);
+
+	s_mark_end(s);
+	channel_send(s, rdpdr_channel);
+}
+
+static void
+rdpdr_process(STREAM s)
+{
+	uint32 handle;
+	uint16 vmin;
+	uint16 component;
+	uint16 pakid;
+
+#if WITH_DEBUG_RDP5
+	printf("--- rdpdr_process ---\n");
+	hexdump(s->p, s->end - s->p);
+#endif
+
+	in_uint16(s, component);
+	in_uint16(s, pakid);
+
+	if (component == RDPDR_CTYP_CORE)
+	{
+		switch (pakid)
+		{
+			case PAKID_CORE_DEVICE_IOREQUEST:
+				rdpdr_process_irp(s);
+				break;
+
+			case PAKID_CORE_SERVER_ANNOUNCE:
+				/* DR_CORE_SERVER_ANNOUNCE_REQ */
+				in_uint8s(s, 2);	/* skip versionMajor */
+				in_uint16_le(s, vmin);	/* VersionMinor */
+				in_uint32_le(s, g_client_id);	/* ClientID */
+
+				/* The RDP client is responsibility to provide a random client id
+				   if server version is < 12 */
+				if (vmin < 0x000c)
+					g_client_id = 0x815ed39d;	/* IP address (use 127.0.0.1) 0x815ed39d */
+				g_epoch++;
+
+				rdpdr_send_client_announce_reply();
+				rdpdr_send_client_name_request();
+				break;
+
+			case PAKID_CORE_CLIENTID_CONFIRM:
+				rdpdr_send_client_device_list_announce();
+				break;
+
+			case PAKID_CORE_DEVICE_REPLY:
+				in_uint32(s, handle);
+#if WITH_DEBUG_RDP5
+				DEBUG(("RDPDR: Server connected to resource %d\n", handle));
+#endif
+				break;
+
+			case PAKID_CORE_SERVER_CAPABILITY:
+				rdpdr_send_client_capability_response();
+				break;
+
+			default:
+				unimpl("RDPDR pakid 0x%x of component 0x%x\n", pakid, component);
+				break;
+
+		}
+	}
+	else if (component == RDPDR_CTYP_PRN)
+	{
+		if (pakid == PAKID_PRN_CACHE_DATA)
+			printercache_process(s);
+	}
+	else
+		unimpl("RDPDR component 0x%x\n", component);
+}
+
+RD_BOOL
+rdpdr_init()
+{
+	rdpdr_channel =
+		channel_register("rdpdr",
+				 CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,
+				 rdpdr_process);
+
+	return (rdpdr_channel != NULL);
+}
+
+/* Add file descriptors of pending io request to select() */
+void
+rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, RD_BOOL * timeout)
+{
+	uint32 select_timeout = 0;	/* Timeout value to be used for select() (in millisecons). */
+	struct async_iorequest *iorq;
+	char c;
+
+	iorq = g_iorequest;
+	while (iorq != NULL)
+	{
+		if (iorq->fd != 0)
+		{
+			switch (iorq->major)
+			{
+				case IRP_MJ_READ:
+					/* Is this FD valid? FDs will
+					   be invalid when
+					   reconnecting. FIXME: Real
+					   support for reconnects. */
+
+					FD_SET(iorq->fd, rfds);
+					*n = MAX(*n, iorq->fd);
+
+					/* Check if io request timeout is smaller than current (but not 0). */
+					if (iorq->timeout
+					    && (select_timeout == 0
+						|| iorq->timeout < select_timeout))
+					{
+						/* Set new timeout */
+						select_timeout = iorq->timeout;
+						g_min_timeout_fd = iorq->fd;	/* Remember fd */
+						tv->tv_sec = select_timeout / 1000;
+						tv->tv_usec = (select_timeout % 1000) * 1000;
+						*timeout = True;
+						break;
+					}
+					if (iorq->itv_timeout && iorq->partial_len > 0
+					    && (select_timeout == 0
+						|| iorq->itv_timeout < select_timeout))
+					{
+						/* Set new timeout */
+						select_timeout = iorq->itv_timeout;
+						g_min_timeout_fd = iorq->fd;	/* Remember fd */
+						tv->tv_sec = select_timeout / 1000;
+						tv->tv_usec = (select_timeout % 1000) * 1000;
+						*timeout = True;
+						break;
+					}
+					break;
+
+				case IRP_MJ_WRITE:
+					/* FD still valid? See above. */
+					if ((write(iorq->fd, &c, 0) != 0) && (errno == EBADF))
+						break;
+
+					FD_SET(iorq->fd, wfds);
+					*n = MAX(*n, iorq->fd);
+					break;
+
+				case IRP_MJ_DEVICE_CONTROL:
+					if (select_timeout > 5)
+						select_timeout = 5;	/* serial event queue */
+					break;
+
+			}
+
+		}
+
+		iorq = iorq->next;
+	}
+}
+
+struct async_iorequest *
+rdpdr_remove_iorequest(struct async_iorequest *prev, struct async_iorequest *iorq)
+{
+	if (!iorq)
+		return NULL;
+
+	if (iorq->buffer)
+		xfree(iorq->buffer);
+	if (prev)
+	{
+		prev->next = iorq->next;
+		xfree(iorq);
+		iorq = prev->next;
+	}
+	else
+	{
+		/* Even if NULL */
+		g_iorequest = iorq->next;
+		xfree(iorq);
+		iorq = NULL;
+	}
+	return iorq;
+}
+
+/* Check if select() returned with one of the rdpdr file descriptors, and complete io if it did */
+static void
+_rdpdr_check_fds(fd_set * rfds, fd_set * wfds, RD_BOOL timed_out)
+{
+	RD_NTSTATUS status;
+	uint32 result = 0;
+	DEVICE_FNS *fns;
+	struct async_iorequest *iorq;
+	struct async_iorequest *prev;
+	uint32 req_size = 0;
+	uint32 buffer_len;
+	struct stream out;
+	uint8 *buffer = NULL;
+
+
+	if (timed_out)
+	{
+		/* check serial iv_timeout */
+
+		iorq = g_iorequest;
+		prev = NULL;
+		while (iorq != NULL)
+		{
+			if (iorq->fd == g_min_timeout_fd)
+			{
+				if ((iorq->partial_len > 0) &&
+				    (g_rdpdr_device[iorq->device].device_type ==
+				     DEVICE_TYPE_SERIAL))
+				{
+
+					/* iv_timeout between 2 chars, send partial_len */
+					/*printf("RDPDR: IVT total %u bytes read of %u\n", iorq->partial_len, iorq->length); */
+					rdpdr_send_completion(iorq->device,
+							      iorq->id, RD_STATUS_SUCCESS,
+							      iorq->partial_len,
+							      iorq->buffer, iorq->partial_len);
+					iorq = rdpdr_remove_iorequest(prev, iorq);
+					return;
+				}
+				else
+				{
+					break;
+				}
+
+			}
+			else
+			{
+				break;
+			}
+
+
+			prev = iorq;
+			if (iorq)
+				iorq = iorq->next;
+
+		}
+
+		rdpdr_abort_io(g_min_timeout_fd, 0, RD_STATUS_TIMEOUT);
+		return;
+	}
+
+	iorq = g_iorequest;
+	prev = NULL;
+	while (iorq != NULL)
+	{
+		if (iorq->fd != 0)
+		{
+			switch (iorq->major)
+			{
+				case IRP_MJ_READ:
+					if (FD_ISSET(iorq->fd, rfds))
+					{
+						/* Read the data */
+						fns = iorq->fns;
+
+						req_size =
+							(iorq->length - iorq->partial_len) >
+							8192 ? 8192 : (iorq->length -
+								       iorq->partial_len);
+						/* never read larger chunks than 8k - chances are that it will block */
+						status = fns->read(iorq->fd,
+								   iorq->buffer + iorq->partial_len,
+								   req_size, iorq->offset, &result);
+
+						if ((long) result > 0)
+						{
+							iorq->partial_len += result;
+							iorq->offset += result;
+						}
+#if WITH_DEBUG_RDP5
+						DEBUG(("RDPDR: %d bytes of data read\n", result));
+#endif
+						/* only delete link if all data has been transfered */
+						/* or if result was 0 and status success - EOF      */
+						if ((iorq->partial_len == iorq->length) ||
+						    (result == 0))
+						{
+#if WITH_DEBUG_RDP5
+							DEBUG(("RDPDR: AIO total %u bytes read of %u\n", iorq->partial_len, iorq->length));
+#endif
+							rdpdr_send_completion(iorq->device,
+									      iorq->id, status,
+									      iorq->partial_len,
+									      iorq->buffer,
+									      iorq->partial_len);
+							iorq = rdpdr_remove_iorequest(prev, iorq);
+						}
+					}
+					break;
+				case IRP_MJ_WRITE:
+					if (FD_ISSET(iorq->fd, wfds))
+					{
+						/* Write data. */
+						fns = iorq->fns;
+
+						req_size =
+							(iorq->length - iorq->partial_len) >
+							8192 ? 8192 : (iorq->length -
+								       iorq->partial_len);
+
+						/* never write larger chunks than 8k - chances are that it will block */
+						status = fns->write(iorq->fd,
+								    iorq->buffer +
+								    iorq->partial_len, req_size,
+								    iorq->offset, &result);
+
+						if ((long) result > 0)
+						{
+							iorq->partial_len += result;
+							iorq->offset += result;
+						}
+
+#if WITH_DEBUG_RDP5
+						DEBUG(("RDPDR: %d bytes of data written\n",
+						       result));
+#endif
+						/* only delete link if all data has been transfered */
+						/* or we couldn't write */
+						if ((iorq->partial_len == iorq->length)
+						    || (result == 0))
+						{
+#if WITH_DEBUG_RDP5
+							DEBUG(("RDPDR: AIO total %u bytes written of %u\n", iorq->partial_len, iorq->length));
+#endif
+							rdpdr_send_completion(iorq->device,
+									      iorq->id, status,
+									      iorq->partial_len,
+									      (uint8 *) "", 1);
+
+							iorq = rdpdr_remove_iorequest(prev, iorq);
+						}
+					}
+					break;
+				case IRP_MJ_DEVICE_CONTROL:
+					if (serial_get_event(iorq->fd, &result))
+					{
+						buffer = (uint8 *) xrealloc((void *) buffer, 0x14);
+						out.data = out.p = buffer;
+						out.size = sizeof(buffer);
+						out_uint32_le(&out, result);
+						result = buffer_len = out.p - out.data;
+						status = RD_STATUS_SUCCESS;
+						rdpdr_send_completion(iorq->device, iorq->id,
+								      status, result, buffer,
+								      buffer_len);
+						xfree(buffer);
+						iorq = rdpdr_remove_iorequest(prev, iorq);
+					}
+
+					break;
+			}
+
+		}
+		prev = iorq;
+		if (iorq)
+			iorq = iorq->next;
+	}
+
+	/* Check notify */
+	iorq = g_iorequest;
+	prev = NULL;
+	while (iorq != NULL)
+	{
+		if (iorq->fd != 0)
+		{
+			switch (iorq->major)
+			{
+
+				case IRP_MJ_DIRECTORY_CONTROL:
+					if (g_rdpdr_device[iorq->device].device_type ==
+					    DEVICE_TYPE_DISK)
+					{
+
+						if (g_notify_stamp)
+						{
+							g_notify_stamp = False;
+							status = disk_check_notify(iorq->fd);
+							if (status != RD_STATUS_PENDING)
+							{
+								rdpdr_send_completion(iorq->device,
+										      iorq->id,
+										      status, 0,
+										      NULL, 0);
+								iorq = rdpdr_remove_iorequest(prev,
+											      iorq);
+							}
+						}
+					}
+					break;
+
+
+
+			}
+		}
+
+		prev = iorq;
+		if (iorq)
+			iorq = iorq->next;
+	}
+
+}
+
+void
+rdpdr_check_fds(fd_set * rfds, fd_set * wfds, RD_BOOL timed_out)
+{
+	fd_set dummy;
+
+
+	FD_ZERO(&dummy);
+
+
+	/* fist check event queue only,
+	   any serial wait event must be done before read block will be sent
+	 */
+
+	_rdpdr_check_fds(&dummy, &dummy, False);
+	_rdpdr_check_fds(rfds, wfds, timed_out);
+}
+
+
+/* Abort a pending io request for a given handle and major */
+RD_BOOL
+rdpdr_abort_io(uint32 fd, uint32 major, RD_NTSTATUS status)
+{
+	uint32 result;
+	struct async_iorequest *iorq;
+	struct async_iorequest *prev;
+
+	iorq = g_iorequest;
+	prev = NULL;
+	while (iorq != NULL)
+	{
+		/* Only remove from table when major is not set, or when correct major is supplied.
+		   Abort read should not abort a write io request. */
+		if ((iorq->fd == fd) && (major == 0 || iorq->major == major))
+		{
+			result = 0;
+			rdpdr_send_completion(iorq->device, iorq->id, status, result, (uint8 *) "",
+					      1);
+
+			iorq = rdpdr_remove_iorequest(prev, iorq);
+			return True;
+		}
+
+		prev = iorq;
+		iorq = iorq->next;
+	}
+
+	return False;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/rdpsnd.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdpsnd.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdpsnd.c	(revision 55121)
@@ -0,0 +1,983 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Sound Channel Process Functions
+   Copyright 2006-2010 Pierre Ossman <ossman@cendio.se> for Cendio AB
+   Copyright 2009-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
+   Copyright (C) GuoJunBo <guojunbo@ict.ac.cn> 2003
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <assert.h>
+
+#include "rdesktop.h"
+#include "rdpsnd.h"
+#include "rdpsnd_dsp.h"
+
+#define RDPSND_CLOSE		1
+#define RDPSND_WRITE		2
+#define RDPSND_SET_VOLUME	3
+#define RDPSND_UNKNOWN4		4
+#define RDPSND_COMPLETION	5
+#define RDPSND_PING			6
+#define RDPSND_NEGOTIATE	7
+
+#define RDPSND_REC_NEGOTIATE	39
+#define RDPSND_REC_START		40
+#define RDPSND_REC_STOP			41
+#define RDPSND_REC_DATA			42
+#define RDPSND_REC_SET_VOLUME	43
+
+/* Special flag for RDPSND recording extension,
+   not defined in MS specs.
+
+   See doc/rdpsnd-rec.txt for more information.
+*/
+#define RDPSND_FLAG_RECORD		0x00800000
+
+#define MAX_FORMATS		10
+#define MAX_QUEUE		50
+
+extern RD_BOOL g_rdpsnd;
+
+static VCHANNEL *rdpsnd_channel;
+static VCHANNEL *rdpsnddbg_channel;
+static struct audio_driver *drivers = NULL;
+struct audio_driver *current_driver = NULL;
+
+static RD_BOOL rdpsnd_negotiated;
+static RD_BOOL rdpsnd_rec_negotiated;
+
+static RD_BOOL device_open;
+static RD_BOOL rec_device_open;
+
+static RD_WAVEFORMATEX formats[MAX_FORMATS];
+static unsigned int format_count;
+static unsigned int current_format;
+
+static RD_WAVEFORMATEX rec_formats[MAX_FORMATS];
+static unsigned int rec_format_count;
+static unsigned int rec_current_format;
+
+unsigned int queue_hi, queue_lo, queue_pending;
+struct audio_packet packet_queue[MAX_QUEUE];
+
+static char record_buffer[8192];
+static uint32 record_buffer_size;
+
+static uint8 packet_opcode;
+static struct stream packet;
+
+void (*wave_out_play) (void);
+
+static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
+static void rdpsnd_queue_init(void);
+static void rdpsnd_queue_clear(void);
+static void rdpsnd_queue_complete_pending(void);
+static long rdpsnd_queue_next_completion(void);
+
+static STREAM
+rdpsnd_init_packet(uint16 type, uint16 size)
+{
+	STREAM s;
+
+	s = channel_init(rdpsnd_channel, size + 4);
+	out_uint16_le(s, type);
+	out_uint16_le(s, size);
+	return s;
+}
+
+static void
+rdpsnd_send(STREAM s)
+{
+	channel_send(s, rdpsnd_channel);
+}
+
+static void
+rdpsnd_send_completion(uint16 tick, uint8 packet_index)
+{
+	STREAM s;
+
+	s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
+	out_uint16_le(s, tick);
+	out_uint8(s, packet_index);
+	out_uint8(s, 0);
+	s_mark_end(s);
+	rdpsnd_send(s);
+
+	DEBUG_SOUND(("RDPSND: -> RDPSND_COMPLETION(tick: %u, index: %u)\n",
+		     (unsigned) tick, (unsigned) packet_index));
+}
+
+static void
+rdpsnd_flush_record(void)
+{
+	STREAM s;
+	unsigned int chunk_size;
+	char *data;
+
+	if (record_buffer_size == 0)
+		return;
+
+	assert(record_buffer_size <= sizeof(record_buffer));
+
+	data = record_buffer;
+
+	/*
+	 * Microsoft's RDP server keeps dropping chunks, so we need to
+	 * transmit everything inside one channel fragment or we risk
+	 * making the rdpsnd server go out of sync with the byte stream.
+	 */
+	while (record_buffer_size)
+	{
+		if (record_buffer_size < 1596)
+			chunk_size = record_buffer_size;
+		else
+			chunk_size = 1596;
+
+		s = rdpsnd_init_packet(RDPSND_REC_DATA, chunk_size);
+		out_uint8p(s, data, chunk_size);
+
+		s_mark_end(s);
+		rdpsnd_send(s);
+
+		data = data + chunk_size;
+		record_buffer_size -= chunk_size;
+
+		DEBUG_SOUND(("RDPSND: -> RDPSND_REC_DATA(length: %u)\n", (unsigned) chunk_size));
+	}
+
+	record_buffer_size = 0;
+}
+
+static void
+rdpsnd_clear_record(void)
+{
+	/*
+	 * Silently drop everything we have in the record buffer as
+	 * we've somehow gotten a reset in regard to the server.
+	 */
+	record_buffer_size = 0;
+}
+
+void
+rdpsnd_record(const void *data, unsigned int size)
+{
+	uint32 remain, chunk;
+
+	assert(rec_device_open);
+
+	while (size)
+	{
+		remain = sizeof(record_buffer) - record_buffer_size;
+
+		if (size >= remain)
+			chunk = remain;
+		else
+			chunk = size;
+
+		memcpy(record_buffer + record_buffer_size, data, chunk);
+
+#ifdef B_ENDIAN
+		if (current_driver->need_byteswap_on_be)
+			rdpsnd_dsp_swapbytes(record_buffer + record_buffer_size,
+					     chunk, &rec_formats[rec_current_format]);
+#endif
+
+		record_buffer_size += chunk;
+
+		data = (const char *) data + chunk;
+		size -= chunk;
+
+		if (record_buffer_size == sizeof(record_buffer))
+			rdpsnd_flush_record();
+	}
+}
+
+static RD_BOOL
+rdpsnd_auto_select(void)
+{
+	static RD_BOOL failed = False;
+
+	if (!failed)
+	{
+		current_driver = drivers;
+		while (current_driver != NULL)
+		{
+			DEBUG(("trying %s...\n", current_driver->name));
+			if (current_driver->wave_out_open())
+			{
+				DEBUG(("selected %s\n", current_driver->name));
+				current_driver->wave_out_close();
+				return True;
+			}
+			current_driver = current_driver->next;
+		}
+
+		warning("no working audio-driver found\n");
+		failed = True;
+		current_driver = NULL;
+	}
+
+	return False;
+}
+
+static void
+rdpsnd_process_negotiate(STREAM in)
+{
+	uint16 in_format_count, i;
+	uint8 pad;
+	uint16 version;
+	RD_WAVEFORMATEX *format;
+	STREAM out;
+	RD_BOOL device_available = False;
+	int readcnt;
+	int discardcnt;
+
+	in_uint8s(in, 14);	/* initial bytes not valid from server */
+	in_uint16_le(in, in_format_count);
+	in_uint8(in, pad);
+	in_uint16_le(in, version);
+	in_uint8s(in, 1);	/* padding */
+
+	DEBUG_SOUND(("RDPSND: RDPSND_NEGOTIATE(formats: %d, pad: 0x%02x, version: %x)\n",
+		     (int) in_format_count, (unsigned) pad, (unsigned) version));
+
+	if (rdpsnd_negotiated)
+	{
+		error("RDPSND: Extra RDPSND_NEGOTIATE in the middle of a session\n");
+		/* Do a complete reset of the sound state */
+		rdpsnd_reset_state();
+	}
+
+	if (!current_driver && g_rdpsnd)
+		device_available = rdpsnd_auto_select();
+
+	if (current_driver && !device_available && current_driver->wave_out_open())
+	{
+		current_driver->wave_out_close();
+		device_available = True;
+	}
+
+	format_count = 0;
+	if (s_check_rem(in, 18 * in_format_count))
+	{
+		for (i = 0; i < in_format_count; i++)
+		{
+			format = &formats[format_count];
+			in_uint16_le(in, format->wFormatTag);
+			in_uint16_le(in, format->nChannels);
+			in_uint32_le(in, format->nSamplesPerSec);
+			in_uint32_le(in, format->nAvgBytesPerSec);
+			in_uint16_le(in, format->nBlockAlign);
+			in_uint16_le(in, format->wBitsPerSample);
+			in_uint16_le(in, format->cbSize);
+
+			/* read in the buffer of unknown use */
+			readcnt = format->cbSize;
+			discardcnt = 0;
+			if (format->cbSize > MAX_CBSIZE)
+			{
+				fprintf(stderr, "cbSize too large for buffer: %d\n",
+					format->cbSize);
+				readcnt = MAX_CBSIZE;
+				discardcnt = format->cbSize - MAX_CBSIZE;
+			}
+			in_uint8a(in, format->cb, readcnt);
+			in_uint8s(in, discardcnt);
+
+			if (current_driver && current_driver->wave_out_format_supported(format))
+			{
+				format_count++;
+				if (format_count == MAX_FORMATS)
+					break;
+			}
+		}
+	}
+
+	out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
+
+	uint32 flags = TSSNDCAPS_VOLUME;
+
+	/* if sound is enabled, set snd caps to alive to enable
+	   transmision of audio from server */
+	if (g_rdpsnd)
+	{
+		flags |= TSSNDCAPS_ALIVE;
+		flags |= RDPSND_FLAG_RECORD;
+	}
+	out_uint32_le(out, flags);	/* TSSNDCAPS flags */
+
+	out_uint32(out, 0xffffffff);	/* volume */
+	out_uint32(out, 0);	/* pitch */
+	out_uint16(out, 0);	/* UDP port */
+
+	out_uint16_le(out, format_count);
+	out_uint8(out, 0);	/* padding */
+	out_uint16_le(out, 2);	/* version */
+	out_uint8(out, 0);	/* padding */
+
+	for (i = 0; i < format_count; i++)
+	{
+		format = &formats[i];
+		out_uint16_le(out, format->wFormatTag);
+		out_uint16_le(out, format->nChannels);
+		out_uint32_le(out, format->nSamplesPerSec);
+		out_uint32_le(out, format->nAvgBytesPerSec);
+		out_uint16_le(out, format->nBlockAlign);
+		out_uint16_le(out, format->wBitsPerSample);
+		out_uint16(out, 0);	/* cbSize */
+	}
+
+	s_mark_end(out);
+
+	DEBUG_SOUND(("RDPSND: -> RDPSND_NEGOTIATE(formats: %d)\n", (int) format_count));
+
+	rdpsnd_send(out);
+
+	rdpsnd_negotiated = True;
+}
+
+static void
+rdpsnd_process_ping(STREAM in)
+{
+	uint16 tick;
+	STREAM out;
+
+	in_uint16_le(in, tick);
+
+	DEBUG_SOUND(("RDPSND: RDPSND_PING(tick: 0x%04x)\n", (unsigned) tick));
+
+	out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
+	out_uint16_le(out, tick);
+	out_uint16_le(out, 0);
+	s_mark_end(out);
+	rdpsnd_send(out);
+
+	DEBUG_SOUND(("RDPSND: -> (tick: 0x%04x)\n", (unsigned) tick));
+}
+
+static void
+rdpsnd_process_rec_negotiate(STREAM in)
+{
+	uint16 in_format_count, i;
+	uint16 version;
+	RD_WAVEFORMATEX *format;
+	STREAM out;
+	RD_BOOL device_available = False;
+	int readcnt;
+	int discardcnt;
+
+	in_uint8s(in, 8);	/* initial bytes not valid from server */
+	in_uint16_le(in, in_format_count);
+	in_uint16_le(in, version);
+
+	DEBUG_SOUND(("RDPSND: RDPSND_REC_NEGOTIATE(formats: %d, version: %x)\n",
+		     (int) in_format_count, (unsigned) version));
+
+	if (rdpsnd_rec_negotiated)
+	{
+		error("RDPSND: Extra RDPSND_REC_NEGOTIATE in the middle of a session\n");
+		/* Do a complete reset of the sound state */
+		rdpsnd_reset_state();
+	}
+
+	if (!current_driver)
+		device_available = rdpsnd_auto_select();
+
+	if (current_driver && !device_available && current_driver->wave_in_open
+	    && current_driver->wave_in_open())
+	{
+		current_driver->wave_in_close();
+		device_available = True;
+	}
+
+	rec_format_count = 0;
+	if (s_check_rem(in, 18 * in_format_count))
+	{
+		for (i = 0; i < in_format_count; i++)
+		{
+			format = &rec_formats[rec_format_count];
+			in_uint16_le(in, format->wFormatTag);
+			in_uint16_le(in, format->nChannels);
+			in_uint32_le(in, format->nSamplesPerSec);
+			in_uint32_le(in, format->nAvgBytesPerSec);
+			in_uint16_le(in, format->nBlockAlign);
+			in_uint16_le(in, format->wBitsPerSample);
+			in_uint16_le(in, format->cbSize);
+
+			/* read in the buffer of unknown use */
+			readcnt = format->cbSize;
+			discardcnt = 0;
+			if (format->cbSize > MAX_CBSIZE)
+			{
+				fprintf(stderr, "cbSize too large for buffer: %d\n",
+					format->cbSize);
+				readcnt = MAX_CBSIZE;
+				discardcnt = format->cbSize - MAX_CBSIZE;
+			}
+			in_uint8a(in, format->cb, readcnt);
+			in_uint8s(in, discardcnt);
+
+			if (current_driver && current_driver->wave_in_format_supported
+			    && current_driver->wave_in_format_supported(format))
+			{
+				rec_format_count++;
+				if (rec_format_count == MAX_FORMATS)
+					break;
+			}
+		}
+	}
+
+	out = rdpsnd_init_packet(RDPSND_REC_NEGOTIATE, 12 + 18 * rec_format_count);
+	out_uint32_le(out, 0x00000000);	/* flags */
+	out_uint32_le(out, 0xffffffff);	/* volume */
+	out_uint16_le(out, rec_format_count);
+	out_uint16_le(out, 1);	/* version */
+
+	for (i = 0; i < rec_format_count; i++)
+	{
+		format = &rec_formats[i];
+		out_uint16_le(out, format->wFormatTag);
+		out_uint16_le(out, format->nChannels);
+		out_uint32_le(out, format->nSamplesPerSec);
+		out_uint32_le(out, format->nAvgBytesPerSec);
+		out_uint16_le(out, format->nBlockAlign);
+		out_uint16_le(out, format->wBitsPerSample);
+		out_uint16(out, 0);	/* cbSize */
+	}
+
+	s_mark_end(out);
+
+	DEBUG_SOUND(("RDPSND: -> RDPSND_REC_NEGOTIATE(formats: %d)\n", (int) rec_format_count));
+
+	rdpsnd_send(out);
+
+	rdpsnd_rec_negotiated = True;
+}
+
+static void
+rdpsnd_process_packet(uint8 opcode, STREAM s)
+{
+	uint16 vol_left, vol_right;
+	static uint16 tick, format;
+	static uint8 packet_index;
+
+	switch (opcode)
+	{
+		case RDPSND_WRITE:
+			in_uint16_le(s, tick);
+			in_uint16_le(s, format);
+			in_uint8(s, packet_index);
+			in_uint8s(s, 3);
+			DEBUG_SOUND(("RDPSND: RDPSND_WRITE(tick: %u, format: %u, index: %u, data: %u bytes)\n", (unsigned) tick, (unsigned) format, (unsigned) packet_index, (unsigned) s->size - 8));
+
+			if (format >= MAX_FORMATS)
+			{
+				error("RDPSND: Invalid format index\n");
+				break;
+			}
+
+			if (!device_open || (format != current_format))
+			{
+				/*
+				 * If we haven't selected a device by now, then either
+				 * we've failed to find a working device, or the server
+				 * is sending bogus RDPSND_WRITE.
+				 */
+				if (!current_driver)
+				{
+					rdpsnd_send_completion(tick, packet_index);
+					break;
+				}
+				if (!device_open && !current_driver->wave_out_open())
+				{
+					rdpsnd_send_completion(tick, packet_index);
+					break;
+				}
+				if (!current_driver->wave_out_set_format(&formats[format]))
+				{
+					rdpsnd_send_completion(tick, packet_index);
+					current_driver->wave_out_close();
+					device_open = False;
+					break;
+				}
+				device_open = True;
+				current_format = format;
+			}
+
+			rdpsnd_queue_write(rdpsnd_dsp_process
+					   (s->p, s->end - s->p, current_driver,
+					    &formats[current_format]), tick, packet_index);
+			return;
+			break;
+		case RDPSND_CLOSE:
+			DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));
+			if (device_open)
+				current_driver->wave_out_close();
+			device_open = False;
+			break;
+		case RDPSND_NEGOTIATE:
+			rdpsnd_process_negotiate(s);
+			break;
+		case RDPSND_PING:
+			rdpsnd_process_ping(s);
+			break;
+		case RDPSND_SET_VOLUME:
+			in_uint16_le(s, vol_left);
+			in_uint16_le(s, vol_right);
+			DEBUG_SOUND(("RDPSND: RDPSND_VOLUME(left: 0x%04x (%u %%), right: 0x%04x (%u %%))\n", (unsigned) vol_left, (unsigned) vol_left / 655, (unsigned) vol_right, (unsigned) vol_right / 655));
+			if (device_open)
+				current_driver->wave_out_volume(vol_left, vol_right);
+			break;
+		case RDPSND_REC_NEGOTIATE:
+			rdpsnd_process_rec_negotiate(s);
+			break;
+		case RDPSND_REC_START:
+			in_uint16_le(s, format);
+			DEBUG_SOUND(("RDPSND: RDPSND_REC_START(format: %u)\n", (unsigned) format));
+
+			if (format >= MAX_FORMATS)
+			{
+				error("RDPSND: Invalid format index\n");
+				break;
+			}
+
+			if (rec_device_open)
+			{
+				error("RDPSND: Multiple RDPSND_REC_START\n");
+				break;
+			}
+
+			if (!current_driver->wave_in_open())
+				break;
+
+			if (!current_driver->wave_in_set_format(&rec_formats[format]))
+			{
+				error("RDPSND: Device not accepting format\n");
+				current_driver->wave_in_close();
+				break;
+			}
+			rec_current_format = format;
+			rec_device_open = True;
+			break;
+		case RDPSND_REC_STOP:
+			DEBUG_SOUND(("RDPSND: RDPSND_REC_STOP()\n"));
+			rdpsnd_flush_record();
+			if (rec_device_open)
+				current_driver->wave_in_close();
+			rec_device_open = False;
+			break;
+		case RDPSND_REC_SET_VOLUME:
+			in_uint16_le(s, vol_left);
+			in_uint16_le(s, vol_right);
+			DEBUG_SOUND(("RDPSND: RDPSND_REC_VOLUME(left: 0x%04x (%u %%), right: 0x%04x (%u %%))\n", (unsigned) vol_left, (unsigned) vol_left / 655, (unsigned) vol_right, (unsigned) vol_right / 655));
+			if (rec_device_open)
+				current_driver->wave_in_volume(vol_left, vol_right);
+			break;
+		default:
+			unimpl("RDPSND packet type %x\n", opcode);
+			break;
+	}
+}
+
+static void
+rdpsnd_process(STREAM s)
+{
+	uint16 len;
+
+	while (!s_check_end(s))
+	{
+		/* New packet */
+		if (packet.size == 0)
+		{
+			if ((s->end - s->p) < 4)
+			{
+				error("RDPSND: Split at packet header. Things will go south from here...\n");
+				return;
+			}
+			in_uint8(s, packet_opcode);
+			in_uint8s(s, 1);	/* Padding */
+			in_uint16_le(s, len);
+
+			DEBUG_SOUND(("RDPSND: == Opcode %x Length: %d ==\n",
+				     (int) packet_opcode, (int) len));
+
+			packet.p = packet.data;
+			packet.end = packet.data + len;
+			packet.size = len;
+		}
+		else
+		{
+			len = MIN(s->end - s->p, packet.end - packet.p);
+
+			/* Microsoft's server is so broken it's not even funny... */
+			if (packet_opcode == RDPSND_WRITE)
+			{
+				if ((packet.p - packet.data) < 12)
+					len = MIN(len, 12 - (packet.p - packet.data));
+				else if ((packet.p - packet.data) == 12)
+				{
+					DEBUG_SOUND(("RDPSND: Eating 4 bytes of %d bytes...\n",
+						     len));
+					in_uint8s(s, 4);
+					len -= 4;
+				}
+			}
+
+			in_uint8a(s, packet.p, len);
+			packet.p += len;
+		}
+
+		/* Packet fully assembled */
+		if (packet.p == packet.end)
+		{
+			packet.p = packet.data;
+			rdpsnd_process_packet(packet_opcode, &packet);
+			packet.size = 0;
+		}
+	}
+}
+
+static RD_BOOL
+rdpsnddbg_line_handler(const char *line, void *data)
+{
+#ifdef WITH_DEBUG_SOUND
+	fprintf(stderr, "SNDDBG: %s\n", line);
+#endif
+	return True;
+}
+
+static void
+rdpsnddbg_process(STREAM s)
+{
+	unsigned int pkglen;
+	static char *rest = NULL;
+	char *buf;
+
+	pkglen = s->end - s->p;
+	/* str_handle_lines requires null terminated strings */
+	buf = (char *) xmalloc(pkglen + 1);
+	STRNCPY(buf, (char *) s->p, pkglen + 1);
+
+	str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL);
+
+	xfree(buf);
+}
+
+static void
+rdpsnd_register_drivers(char *options)
+{
+	struct audio_driver **reg;
+
+	/* The order of registrations define the probe-order
+	   when opening the device for the first time */
+	reg = &drivers;
+#if defined(RDPSND_ALSA)
+	*reg = alsa_register(options);
+	assert(*reg);
+	reg = &((*reg)->next);
+#endif
+#if defined(RDPSND_SUN)
+	*reg = sun_register(options);
+	assert(*reg);
+	reg = &((*reg)->next);
+#endif
+#if defined(RDPSND_OSS)
+	*reg = oss_register(options);
+	assert(*reg);
+	reg = &((*reg)->next);
+#endif
+#if defined(RDPSND_SGI)
+	*reg = sgi_register(options);
+	assert(*reg);
+	reg = &((*reg)->next);
+#endif
+#if defined(RDPSND_LIBAO)
+	*reg = libao_register(options);
+	assert(*reg);
+	reg = &((*reg)->next);
+#endif
+	*reg = NULL;
+}
+
+RD_BOOL
+rdpsnd_init(char *optarg)
+{
+	struct audio_driver *pos;
+	char *driver = NULL, *options = NULL;
+
+	drivers = NULL;
+
+	packet.data = (uint8 *) xmalloc(65536);
+	packet.p = packet.end = packet.data;
+	packet.size = 0;
+
+	rdpsnd_channel =
+		channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
+				 rdpsnd_process);
+
+	rdpsnddbg_channel =
+		channel_register("snddbg", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
+				 rdpsnddbg_process);
+
+	if ((rdpsnd_channel == NULL) || (rdpsnddbg_channel == NULL))
+	{
+		error("channel_register\n");
+		return False;
+	}
+
+	rdpsnd_queue_init();
+
+	if (optarg != NULL && strlen(optarg) > 0)
+	{
+		driver = options = optarg;
+
+		while (*options != '\0' && *options != ':')
+			options++;
+
+		if (*options == ':')
+		{
+			*options = '\0';
+			options++;
+		}
+
+		if (*options == '\0')
+			options = NULL;
+	}
+
+	rdpsnd_register_drivers(options);
+
+	if (!driver)
+		return True;
+
+	pos = drivers;
+	while (pos != NULL)
+	{
+		if (!strcmp(pos->name, driver))
+		{
+			DEBUG(("selected %s\n", pos->name));
+			current_driver = pos;
+			return True;
+		}
+		pos = pos->next;
+	}
+	return False;
+}
+
+void
+rdpsnd_reset_state(void)
+{
+	if (device_open)
+		current_driver->wave_out_close();
+	device_open = False;
+	rdpsnd_queue_clear();
+	rdpsnd_negotiated = False;
+
+	if (rec_device_open)
+		current_driver->wave_in_close();
+	rec_device_open = False;
+	rdpsnd_clear_record();
+	rdpsnd_rec_negotiated = False;
+}
+
+
+void
+rdpsnd_show_help(void)
+{
+	struct audio_driver *pos;
+
+	rdpsnd_register_drivers(NULL);
+
+	pos = drivers;
+	while (pos != NULL)
+	{
+		fprintf(stderr, "                     %s:\t%s\n", pos->name, pos->description);
+		pos = pos->next;
+	}
+}
+
+void
+rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
+{
+	long next_pending;
+
+	if (device_open || rec_device_open)
+		current_driver->add_fds(n, rfds, wfds, tv);
+
+	next_pending = rdpsnd_queue_next_completion();
+	if (next_pending >= 0)
+	{
+		long cur_timeout;
+
+		cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
+		if (cur_timeout > next_pending)
+		{
+			tv->tv_sec = next_pending / 1000000;
+			tv->tv_usec = next_pending % 1000000;
+		}
+	}
+}
+
+void
+rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
+{
+	rdpsnd_queue_complete_pending();
+
+	if (device_open || rec_device_open)
+		current_driver->check_fds(rfds, wfds);
+}
+
+static void
+rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
+{
+	struct audio_packet *packet = &packet_queue[queue_hi];
+	unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
+
+	if (next_hi == queue_pending)
+	{
+		error("No space to queue audio packet\n");
+		return;
+	}
+
+	queue_hi = next_hi;
+
+	packet->s = *s;
+	packet->tick = tick;
+	packet->index = index;
+
+	gettimeofday(&packet->arrive_tv, NULL);
+}
+
+struct audio_packet *
+rdpsnd_queue_current_packet(void)
+{
+	return &packet_queue[queue_lo];
+}
+
+RD_BOOL
+rdpsnd_queue_empty(void)
+{
+	return (queue_lo == queue_hi);
+}
+
+static void
+rdpsnd_queue_init(void)
+{
+	queue_pending = queue_lo = queue_hi = 0;
+}
+
+static void
+rdpsnd_queue_clear(void)
+{
+	struct audio_packet *packet;
+
+	/* Go through everything, not just the pending packets */
+	while (queue_pending != queue_hi)
+	{
+		packet = &packet_queue[queue_pending];
+		xfree(packet->s.data);
+		queue_pending = (queue_pending + 1) % MAX_QUEUE;
+	}
+
+	/* Reset everything back to the initial state */
+	queue_pending = queue_lo = queue_hi = 0;
+}
+
+void
+rdpsnd_queue_next(unsigned long completed_in_us)
+{
+	struct audio_packet *packet;
+
+	assert(!rdpsnd_queue_empty());
+
+	packet = &packet_queue[queue_lo];
+
+	gettimeofday(&packet->completion_tv, NULL);
+
+	packet->completion_tv.tv_usec += completed_in_us;
+	packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
+	packet->completion_tv.tv_usec %= 1000000;
+
+	queue_lo = (queue_lo + 1) % MAX_QUEUE;
+
+	rdpsnd_queue_complete_pending();
+}
+
+int
+rdpsnd_queue_next_tick(void)
+{
+	if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
+	{
+		return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
+	}
+	else
+	{
+		return (packet_queue[queue_lo].tick + 65535) % 65536;
+	}
+}
+
+static void
+rdpsnd_queue_complete_pending(void)
+{
+	struct timeval now;
+	long elapsed;
+	struct audio_packet *packet;
+
+	gettimeofday(&now, NULL);
+
+	while (queue_pending != queue_lo)
+	{
+		packet = &packet_queue[queue_pending];
+
+		if (now.tv_sec < packet->completion_tv.tv_sec)
+			break;
+
+		if ((now.tv_sec == packet->completion_tv.tv_sec) &&
+		    (now.tv_usec < packet->completion_tv.tv_usec))
+			break;
+
+		elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
+			(packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
+		elapsed /= 1000;
+
+		xfree(packet->s.data);
+		rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
+		queue_pending = (queue_pending + 1) % MAX_QUEUE;
+	}
+}
+
+static long
+rdpsnd_queue_next_completion(void)
+{
+	struct audio_packet *packet;
+	long remaining;
+	struct timeval now;
+
+	if (queue_pending == queue_lo)
+		return -1;
+
+	gettimeofday(&now, NULL);
+
+	packet = &packet_queue[queue_pending];
+
+	remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
+		(packet->completion_tv.tv_usec - now.tv_usec);
+
+	if (remaining < 0)
+		return 0;
+
+	return remaining;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/rdpsnd.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdpsnd.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdpsnd.h	(revision 55121)
@@ -0,0 +1,59 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   Sound infrastructure
+   Copyright (C) Michael Gernoth 2006-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+struct audio_packet
+{
+	struct stream s;
+	uint16 tick;
+	uint8 index;
+
+	struct timeval arrive_tv;
+	struct timeval completion_tv;
+};
+
+struct audio_driver
+{
+	void (*add_fds) (int *n, fd_set * rfds, fd_set * wfds, struct timeval * tv);
+	void (*check_fds) (fd_set * rfds, fd_set * wfds);
+
+	  RD_BOOL(*wave_out_open) (void);
+	void (*wave_out_close) (void);
+	  RD_BOOL(*wave_out_format_supported) (RD_WAVEFORMATEX * pwfx);
+	  RD_BOOL(*wave_out_set_format) (RD_WAVEFORMATEX * pwfx);
+	void (*wave_out_volume) (uint16 left, uint16 right);
+
+	  RD_BOOL(*wave_in_open) (void);
+	void (*wave_in_close) (void);
+	  RD_BOOL(*wave_in_format_supported) (RD_WAVEFORMATEX * pwfx);
+	  RD_BOOL(*wave_in_set_format) (RD_WAVEFORMATEX * pwfx);
+	void (*wave_in_volume) (uint16 left, uint16 right);
+
+	char *name;
+	char *description;
+	int need_byteswap_on_be;
+	int need_resampling;
+	struct audio_driver *next;
+};
+
+/* Driver register functions */
+struct audio_driver *alsa_register(char *options);
+struct audio_driver *libao_register(char *options);
+struct audio_driver *oss_register(char *options);
+struct audio_driver *sgi_register(char *options);
+struct audio_driver *sun_register(char *options);
Index: /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_alsa.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_alsa.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_alsa.c	(revision 55121)
@@ -0,0 +1,508 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Sound Channel Process Functions - alsa-driver
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
+   Copyright (C) GuoJunBo <guojunbo@ict.ac.cn> 2003
+   Copyright (C) Michael Gernoth <mike@zerfleddert.de> 2006-2008
+   Copyright 2006-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+#include "rdpsnd.h"
+#include "rdpsnd_dsp.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <alsa/asoundlib.h>
+#include <sys/time.h>
+
+#define DEFAULTDEVICE	"default"
+#define MAX_FRAMES	32
+
+static struct pollfd pfds_out[32];
+static int num_fds_out;
+
+static struct pollfd pfds_in[32];
+static int num_fds_in;
+
+static snd_pcm_t *out_handle = NULL;
+static snd_pcm_t *in_handle = NULL;
+
+static RD_BOOL reopened;
+
+static short samplewidth_out;
+static int audiochannels_out;
+static unsigned int rate_out;
+
+static short samplewidth_in;
+static int audiochannels_in;
+static unsigned int rate_in;
+
+static char *pcm_name;
+
+void alsa_play(void);
+void alsa_record(void);
+
+void
+alsa_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
+{
+	int err;
+	struct pollfd *f;
+
+	if (out_handle && !rdpsnd_queue_empty())
+	{
+		num_fds_out = snd_pcm_poll_descriptors_count(out_handle);
+
+		if (num_fds_out > sizeof(pfds_out) / sizeof(*pfds_out))
+			return;
+
+		err = snd_pcm_poll_descriptors(out_handle, pfds_out, num_fds_out);
+		if (err < 0)
+			return;
+
+		for (f = pfds_out; f < &pfds_out[num_fds_out]; f++)
+		{
+			if (f->events & POLLIN)
+				FD_SET(f->fd, rfds);
+			if (f->events & POLLOUT)
+				FD_SET(f->fd, wfds);
+			if (f->fd > *n && (f->events & (POLLIN | POLLOUT)))
+				*n = f->fd;
+		}
+	}
+
+	if (in_handle)
+	{
+		num_fds_in = snd_pcm_poll_descriptors_count(in_handle);
+
+		if (num_fds_in > sizeof(pfds_in) / sizeof(*pfds_in))
+			return;
+
+		err = snd_pcm_poll_descriptors(in_handle, pfds_in, num_fds_in);
+		if (err < 0)
+			return;
+
+		for (f = pfds_in; f < &pfds_in[num_fds_in]; f++)
+		{
+			if (f->events & POLLIN)
+				FD_SET(f->fd, rfds);
+			if (f->events & POLLOUT)
+				FD_SET(f->fd, wfds);
+			if (f->fd > *n && (f->events & (POLLIN | POLLOUT)))
+				*n = f->fd;
+		}
+	}
+}
+
+void
+alsa_check_fds(fd_set * rfds, fd_set * wfds)
+{
+	struct pollfd *f;
+	int err;
+	unsigned short revents;
+
+	if (out_handle && !rdpsnd_queue_empty())
+	{
+		for (f = pfds_out; f < &pfds_out[num_fds_out]; f++)
+		{
+			f->revents = 0;
+			if (f->fd != -1)
+			{
+				/* Fixme: This doesn't properly deal with things like POLLHUP */
+				if (FD_ISSET(f->fd, rfds))
+					f->revents |= POLLIN;
+				if (FD_ISSET(f->fd, wfds))
+					f->revents |= POLLOUT;
+			}
+		}
+
+		err = snd_pcm_poll_descriptors_revents(out_handle, pfds_out, num_fds_out, &revents);
+		if (err < 0)
+			return;
+
+		if (revents & POLLOUT)
+			alsa_play();
+	}
+
+
+	if (in_handle)
+	{
+		for (f = pfds_in; f < &pfds_in[num_fds_in]; f++)
+		{
+			f->revents = 0;
+			if (f->fd != -1)
+			{
+				/* Fixme: This doesn't properly deal with things like POLLHUP */
+				if (FD_ISSET(f->fd, rfds))
+					f->revents |= POLLIN;
+				if (FD_ISSET(f->fd, wfds))
+					f->revents |= POLLOUT;
+			}
+		}
+
+		err = snd_pcm_poll_descriptors_revents(in_handle, pfds_in, num_fds_in, &revents);
+		if (err < 0)
+			return;
+
+		if (revents & POLLIN)
+			alsa_record();
+	}
+}
+
+static RD_BOOL
+alsa_set_format(snd_pcm_t * pcm, RD_WAVEFORMATEX * pwfx)
+{
+	snd_pcm_hw_params_t *hwparams = NULL;
+	int err;
+	unsigned int buffertime;
+	short samplewidth;
+	int audiochannels;
+	unsigned int rate;
+
+	samplewidth = pwfx->wBitsPerSample / 8;
+
+	if ((err = snd_pcm_hw_params_malloc(&hwparams)) < 0)
+	{
+		error("snd_pcm_hw_params_malloc: %s\n", snd_strerror(err));
+		return False;
+	}
+
+	if ((err = snd_pcm_hw_params_any(pcm, hwparams)) < 0)
+	{
+		error("snd_pcm_hw_params_any: %s\n", snd_strerror(err));
+		return False;
+	}
+
+	if ((err = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
+	{
+		error("snd_pcm_hw_params_set_access: %s\n", snd_strerror(err));
+		return False;
+	}
+
+	if (pwfx->wBitsPerSample == 16)
+	{
+		if ((err = snd_pcm_hw_params_set_format(pcm, hwparams, SND_PCM_FORMAT_S16_LE)) < 0)
+		{
+			error("snd_pcm_hw_params_set_format: %s\n", snd_strerror(err));
+			return False;
+		}
+	}
+	else
+	{
+		if ((err = snd_pcm_hw_params_set_format(pcm, hwparams, SND_PCM_FORMAT_S8)) < 0)
+		{
+			error("snd_pcm_hw_params_set_format: %s\n", snd_strerror(err));
+			return False;
+		}
+	}
+
+#if 0
+	if ((err = snd_pcm_hw_params_set_rate_resample(pcm, hwparams, 1)) < 0)
+	{
+		error("snd_pcm_hw_params_set_rate_resample: %s\n", snd_strerror(err));
+		return False;
+	}
+#endif
+
+	rate = pwfx->nSamplesPerSec;
+	if ((err = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rate, 0)) < 0)
+	{
+		error("snd_pcm_hw_params_set_rate_near: %s\n", snd_strerror(err));
+		return False;
+	}
+
+	audiochannels = pwfx->nChannels;
+	if ((err = snd_pcm_hw_params_set_channels(pcm, hwparams, pwfx->nChannels)) < 0)
+	{
+		error("snd_pcm_hw_params_set_channels: %s\n", snd_strerror(err));
+		return False;
+	}
+
+
+	buffertime = 500000;	/* microseconds */
+	if ((err = snd_pcm_hw_params_set_buffer_time_near(pcm, hwparams, &buffertime, 0)) < 0)
+	{
+		error("snd_pcm_hw_params_set_buffer_time_near: %s\n", snd_strerror(err));
+		return False;
+	}
+
+	if ((err = snd_pcm_hw_params(pcm, hwparams)) < 0)
+	{
+		error("snd_pcm_hw_params: %s\n", snd_strerror(err));
+		return False;
+	}
+
+	snd_pcm_hw_params_free(hwparams);
+
+	if ((err = snd_pcm_prepare(pcm)) < 0)
+	{
+		error("snd_pcm_prepare: %s\n", snd_strerror(err));
+		return False;
+	}
+
+	reopened = True;
+
+	return True;
+}
+
+RD_BOOL
+alsa_open_out(void)
+{
+	int err;
+
+	if ((err = snd_pcm_open(&out_handle, pcm_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
+	{
+		error("snd_pcm_open: %s\n", snd_strerror(err));
+		return False;
+	}
+
+	reopened = True;
+
+	return True;
+}
+
+void
+alsa_close_out(void)
+{
+	/* Ack all remaining packets */
+	while (!rdpsnd_queue_empty())
+		rdpsnd_queue_next(0);
+
+	if (out_handle)
+	{
+		snd_pcm_close(out_handle);
+		out_handle = NULL;
+	}
+}
+
+RD_BOOL
+alsa_format_supported(RD_WAVEFORMATEX * pwfx)
+{
+#if 0
+	int err;
+	snd_pcm_hw_params_t *hwparams = NULL;
+
+	if ((err = snd_pcm_hw_params_malloc(&hwparams)) < 0)
+	{
+		error("snd_pcm_hw_params_malloc: %s\n", snd_strerror(err));
+		return False;
+	}
+
+	if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0)
+	{
+		error("snd_pcm_hw_params_malloc: %s\n", snd_strerror(err));
+		return False;
+	}
+	snd_pcm_hw_params_free(hwparams);
+#endif
+
+	if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
+		return False;
+	if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
+		return False;
+	if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
+		return False;
+	if ((pwfx->nSamplesPerSec != 44100) && (pwfx->nSamplesPerSec != 22050))
+		return False;
+
+	return True;
+}
+
+RD_BOOL
+alsa_set_format_out(RD_WAVEFORMATEX * pwfx)
+{
+	if (!alsa_set_format(out_handle, pwfx))
+		return False;
+
+	samplewidth_out = pwfx->wBitsPerSample / 8;
+	audiochannels_out = pwfx->nChannels;
+	rate_out = pwfx->nSamplesPerSec;
+
+	return True;
+}
+
+void
+alsa_play(void)
+{
+	struct audio_packet *packet;
+	STREAM out;
+	int len;
+	static long prev_s, prev_us;
+	unsigned int duration;
+	struct timeval tv;
+	int next_tick;
+
+	if (reopened)
+	{
+		reopened = False;
+		gettimeofday(&tv, NULL);
+		prev_s = tv.tv_sec;
+		prev_us = tv.tv_usec;
+	}
+
+	/* We shouldn't be called if the queue is empty, but still */
+	if (rdpsnd_queue_empty())
+		return;
+
+	packet = rdpsnd_queue_current_packet();
+	out = &packet->s;
+
+	next_tick = rdpsnd_queue_next_tick();
+
+	len = (out->end - out->p) / (samplewidth_out * audiochannels_out);
+	if ((len = snd_pcm_writei(out_handle, out->p, ((MAX_FRAMES < len) ? MAX_FRAMES : len))) < 0)
+	{
+		printf("Fooo!\n");
+		snd_pcm_prepare(out_handle);
+		len = 0;
+	}
+	out->p += (len * samplewidth_out * audiochannels_out);
+
+	gettimeofday(&tv, NULL);
+
+	duration = ((tv.tv_sec - prev_s) * 1000000 + (tv.tv_usec - prev_us)) / 1000;
+
+	if (packet->tick > next_tick)
+		next_tick += 65536;
+
+	if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
+	{
+		snd_pcm_sframes_t delay_frames;
+		unsigned long delay_us;
+
+		prev_s = tv.tv_sec;
+		prev_us = tv.tv_usec;
+
+		if (abs((next_tick - packet->tick) - duration) > 20)
+		{
+			DEBUG(("duration: %d, calc: %d, ", duration, next_tick - packet->tick));
+			DEBUG(("last: %d, is: %d, should: %d\n", packet->tick,
+			       (packet->tick + duration) % 65536, next_tick % 65536));
+		}
+
+		if (snd_pcm_delay(out_handle, &delay_frames) < 0)
+			delay_frames = out->size / (samplewidth_out * audiochannels_out);
+		if (delay_frames < 0)
+			delay_frames = 0;
+
+		delay_us = delay_frames * (1000000 / rate_out);
+
+		rdpsnd_queue_next(delay_us);
+	}
+}
+
+RD_BOOL
+alsa_open_in(void)
+{
+	int err;
+
+	if ((err =
+	     snd_pcm_open(&in_handle, pcm_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0)
+	{
+		error("snd_pcm_open: %s\n", snd_strerror(err));
+		return False;
+	}
+
+	return True;
+}
+
+void
+alsa_close_in(void)
+{
+	if (in_handle)
+	{
+		snd_pcm_close(in_handle);
+		in_handle = NULL;
+	}
+}
+
+RD_BOOL
+alsa_set_format_in(RD_WAVEFORMATEX * pwfx)
+{
+	int err;
+
+	if (!alsa_set_format(in_handle, pwfx))
+		return False;
+
+	if ((err = snd_pcm_start(in_handle)) < 0)
+	{
+		error("snd_pcm_start: %s\n", snd_strerror(err));
+		return False;
+	}
+
+	samplewidth_in = pwfx->wBitsPerSample / 8;
+	audiochannels_in = pwfx->nChannels;
+	rate_in = pwfx->nSamplesPerSec;
+
+	return True;
+}
+
+void
+alsa_record(void)
+{
+	int len;
+	char buffer[32768];
+
+	len = snd_pcm_readi(in_handle, buffer,
+			    sizeof(buffer) / (samplewidth_in * audiochannels_in));
+	if (len < 0)
+	{
+		snd_pcm_prepare(in_handle);
+		len = 0;
+	}
+
+	rdpsnd_record(buffer, len * samplewidth_in * audiochannels_in);
+}
+
+struct audio_driver *
+alsa_register(char *options)
+{
+	static struct audio_driver alsa_driver;
+
+	memset(&alsa_driver, 0, sizeof(alsa_driver));
+
+	alsa_driver.name = "alsa";
+	alsa_driver.description = "ALSA output driver, default device: " DEFAULTDEVICE;
+
+	alsa_driver.add_fds = alsa_add_fds;
+	alsa_driver.check_fds = alsa_check_fds;
+
+	alsa_driver.wave_out_open = alsa_open_out;
+	alsa_driver.wave_out_close = alsa_close_out;
+	alsa_driver.wave_out_format_supported = alsa_format_supported;
+	alsa_driver.wave_out_set_format = alsa_set_format_out;
+	alsa_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
+
+	alsa_driver.wave_in_open = alsa_open_in;
+	alsa_driver.wave_in_close = alsa_close_in;
+	alsa_driver.wave_in_format_supported = alsa_format_supported;
+	alsa_driver.wave_in_set_format = alsa_set_format_in;
+	alsa_driver.wave_in_volume = NULL;	/* FIXME */
+
+	alsa_driver.need_byteswap_on_be = 0;
+	alsa_driver.need_resampling = 0;
+
+	if (options)
+	{
+		pcm_name = xstrdup(options);
+	}
+	else
+	{
+		pcm_name = DEFAULTDEVICE;
+	}
+
+	return &alsa_driver;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_dsp.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_dsp.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_dsp.c	(revision 55121)
@@ -0,0 +1,424 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   Sound DSP routines
+   Copyright (C) Michael Gernoth <mike@zerfleddert.de> 2006-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <strings.h>
+
+#include "rdesktop.h"
+#include "rdpsnd.h"
+#include "rdpsnd_dsp.h"
+
+#ifdef HAVE_LIBSAMPLERATE
+#include <samplerate.h>
+
+#define SRC_CONVERTER SRC_SINC_MEDIUM_QUALITY
+#endif
+
+#define MAX_VOLUME 65535
+
+static uint16 softvol_left = MAX_VOLUME;
+static uint16 softvol_right = MAX_VOLUME;
+static uint32 resample_to_srate = 44100;
+static uint16 resample_to_bitspersample = 16;
+static uint16 resample_to_channels = 2;
+#ifdef HAVE_LIBSAMPLERATE
+static SRC_STATE *src_converter = NULL;
+#endif
+
+void
+rdpsnd_dsp_softvol_set(uint16 left, uint16 right)
+{
+	softvol_left = left;
+	softvol_right = right;
+	DEBUG(("rdpsnd_dsp_softvol_set: left: %u, right: %u\n", left, right));
+}
+
+void
+rdpsnd_dsp_softvol(unsigned char *buffer, unsigned int size, RD_WAVEFORMATEX * format)
+{
+	unsigned int factor_left, factor_right;
+	unsigned char *posin = buffer;
+	unsigned char *posout = buffer;
+
+	if ((softvol_left == MAX_VOLUME) && (softvol_right == MAX_VOLUME))
+		return;
+
+	factor_left = (softvol_left * 256) / MAX_VOLUME;
+	factor_right = (softvol_right * 256) / MAX_VOLUME;
+
+	if (format->nChannels == 1)
+	{
+		factor_left = factor_right = (factor_left + factor_right) / 2;
+	}
+
+	if (format->wBitsPerSample == 8)
+	{
+		sint8 val;
+
+		while (posout < buffer + size)
+		{
+			/* Left */
+			val = *posin++;
+			val = (val * factor_left) >> 8;
+			*posout++ = val;
+
+			/* Right */
+			val = *posin++;
+			val = (val * factor_right) >> 8;
+			*posout++ = val;
+		}
+	}
+	else
+	{
+		sint16 val;
+
+		while (posout < buffer + size)
+		{
+			/* Left */
+			val = *posin++;
+			val |= *posin++ << 8;
+			val = (val * factor_left) >> 8;
+			*posout++ = val & 0xff;
+			*posout++ = val >> 8;
+
+			/* Right */
+			val = *posin++;
+			val |= *posin++ << 8;
+			val = (val * factor_right) >> 8;
+			*posout++ = val & 0xff;
+			*posout++ = val >> 8;
+		}
+	}
+
+	DEBUG(("using softvol with factors left: %d, right: %d (%d/%d)\n", factor_left,
+	       factor_right, format->wBitsPerSample, format->nChannels));
+}
+
+void
+rdpsnd_dsp_swapbytes(unsigned char *buffer, unsigned int size, RD_WAVEFORMATEX * format)
+{
+	int i;
+	uint8 swap;
+
+	if (format->wBitsPerSample == 8)
+		return;
+
+	if (size & 0x1)
+		warning("badly aligned sound data");
+
+	for (i = 0; i < (int) size; i += 2)
+	{
+		swap = *(buffer + i);
+		*(buffer + i) = *(buffer + i + 1);
+		*(buffer + i + 1) = swap;
+	}
+}
+
+RD_BOOL
+rdpsnd_dsp_resample_set(uint32 device_srate, uint16 device_bitspersample, uint16 device_channels)
+{
+#ifdef HAVE_LIBSAMPLERATE
+	int err;
+#endif
+
+	if (device_bitspersample != 16 && device_bitspersample != 8)
+		return False;
+
+	if (device_channels != 1 && device_channels != 2)
+		return False;
+
+	resample_to_srate = device_srate;
+	resample_to_bitspersample = device_bitspersample;
+	resample_to_channels = device_channels;
+
+#ifdef HAVE_LIBSAMPLERATE
+	if (src_converter != NULL)
+		src_converter = src_delete(src_converter);
+
+	if ((src_converter = src_new(SRC_CONVERTER, device_channels, &err)) == NULL)
+	{
+		warning("src_new failed: %d!\n", err);
+		return False;
+	}
+#endif
+
+	return True;
+}
+
+RD_BOOL
+rdpsnd_dsp_resample_supported(RD_WAVEFORMATEX * format)
+{
+	if (format->wFormatTag != WAVE_FORMAT_PCM)
+		return False;
+	if ((format->nChannels != 1) && (format->nChannels != 2))
+		return False;
+	if ((format->wBitsPerSample != 8) && (format->wBitsPerSample != 16))
+		return False;
+
+	return True;
+}
+
+uint32
+rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
+		    RD_WAVEFORMATEX * format, RD_BOOL stream_be)
+{
+#ifdef HAVE_LIBSAMPLERATE
+	SRC_DATA resample_data;
+	float *infloat, *outfloat;
+	int err;
+#else
+	int ratio1k = (resample_to_srate * 1000) / format->nSamplesPerSec;
+#endif
+	int innum, outnum;
+	unsigned char *tmpdata = NULL, *tmp = NULL;
+	int samplewidth = format->wBitsPerSample / 8;
+	int outsize = 0;
+	int i;
+
+	if ((resample_to_bitspersample == format->wBitsPerSample) &&
+	    (resample_to_channels == format->nChannels) &&
+	    (resample_to_srate == format->nSamplesPerSec))
+		return 0;
+
+#ifdef B_ENDIAN
+	if (!stream_be)
+		rdpsnd_dsp_swapbytes(in, size, format);
+#endif
+
+	if (resample_to_channels != format->nChannels)
+	{
+		int newsize = (size / format->nChannels) * resample_to_channels;
+		tmpdata = (unsigned char *) xmalloc(newsize);
+
+		for (i = 0; i < newsize / samplewidth; i++)
+		{
+			if (format->nChannels > resample_to_channels)
+				memcpy(tmpdata + (i * samplewidth),
+				       in +
+				       (((i * format->nChannels) / resample_to_channels) *
+					samplewidth), samplewidth);
+			else
+				memcpy(tmpdata + (i * samplewidth),
+				       in +
+				       (((i / resample_to_channels) * format->nChannels +
+					 (i % format->nChannels)) * samplewidth), samplewidth);
+
+		}
+
+		in = tmpdata;
+		size = newsize;
+	}
+
+
+	/* Expand 8bit input-samples to 16bit */
+#ifndef HAVE_LIBSAMPLERATE	/* libsamplerate needs 16bit samples */
+	if (format->wBitsPerSample != resample_to_bitspersample)
+#endif
+	{
+		/* source: 8 bit, dest: 16bit */
+		if (format->wBitsPerSample == 8)
+		{
+			tmp = tmpdata;
+			tmpdata = (unsigned char *) xmalloc(size * 2);
+			for (i = 0; i < (int) size; i++)
+			{
+				tmpdata[i * 2] = in[i];
+				tmpdata[(i * 2) + 1] = 0x00;
+			}
+			in = tmpdata;
+			samplewidth = 16 / 2;
+			size *= 2;
+
+			if (tmp != NULL)
+				xfree(tmp);
+		}
+	}
+
+	innum = size / samplewidth;
+
+	/* Do the resampling */
+#ifdef HAVE_LIBSAMPLERATE
+	if (src_converter == NULL)
+	{
+		warning("no samplerate converter available!\n");
+		return 0;
+	}
+
+	outnum = ((float) innum * ((float) resample_to_srate / (float) format->nSamplesPerSec)) + 1;
+
+	infloat = (float *) xmalloc(sizeof(float) * innum);
+	outfloat = (float *) xmalloc(sizeof(float) * outnum);
+
+	src_short_to_float_array((short *) in, infloat, innum);
+
+	bzero(&resample_data, sizeof(resample_data));
+	resample_data.data_in = infloat;
+	resample_data.data_out = outfloat;
+	resample_data.input_frames = innum / resample_to_channels;
+	resample_data.output_frames = outnum / resample_to_channels;
+	resample_data.src_ratio = (double) resample_to_srate / (double) format->nSamplesPerSec;
+	resample_data.end_of_input = 0;
+
+	if ((err = src_process(src_converter, &resample_data)) != 0)
+		error("src_process: %s", src_strerror(err));
+
+	xfree(infloat);
+
+	outsize = resample_data.output_frames_gen * resample_to_channels * samplewidth;
+	*out = (unsigned char *) xmalloc(outsize);
+	src_float_to_short_array(outfloat, (short *) *out,
+				 resample_data.output_frames_gen * resample_to_channels);
+	xfree(outfloat);
+
+#else
+	/* Michaels simple linear resampler */
+	if (resample_to_srate < format->nSamplesPerSec)
+	{
+		warning("downsampling currently not supported!\n");
+		return 0;
+	}
+
+	outnum = (innum * ratio1k) / 1000;
+
+	outsize = outnum * samplewidth;
+	*out = (unsigned char *) xmalloc(outsize);
+	bzero(*out, outsize);
+
+	for (i = 0; i < outsize / (resample_to_channels * samplewidth); i++)
+	{
+		int source = (i * 1000) / ratio1k;
+#if 0				/* Partial for linear resampler */
+		int part = (i * 100000) / ratio1k - source * 100;
+#endif
+		int j;
+
+		if (source * resample_to_channels + samplewidth > (int) size)
+			break;
+
+#if 0				/* Linear resampling, TODO: soundquality fixes (LP filter) */
+		if (samplewidth == 1)
+		{
+			sint8 cval1, cval2;
+			for (j = 0; j < resample_to_channels; j++)
+			{
+				memcpy(&cval1,
+				       in + (source * resample_to_channels * samplewidth) +
+				       (samplewidth * j), samplewidth);
+				memcpy(&cval2,
+				       in + ((source + 1) * resample_to_channels * samplewidth) +
+				       (samplewidth * j), samplewidth);
+
+				cval1 += (sint8) (cval2 * part) / 100;
+
+				memcpy(*out + (i * resample_to_channels * samplewidth) +
+				       (samplewidth * j), &cval1, samplewidth);
+			}
+		}
+		else
+		{
+			sint16 sval1, sval2;
+			for (j = 0; j < resample_to_channels; j++)
+			{
+				memcpy(&sval1,
+				       in + (source * resample_to_channels * samplewidth) +
+				       (samplewidth * j), samplewidth);
+				memcpy(&sval2,
+				       in + ((source + 1) * resample_to_channels * samplewidth) +
+				       (samplewidth * j), samplewidth);
+
+				sval1 += (sint16) (sval2 * part) / 100;
+
+				memcpy(*out + (i * resample_to_channels * samplewidth) +
+				       (samplewidth * j), &sval1, samplewidth);
+			}
+		}
+#else /* Nearest neighbor search */
+		for (j = 0; j < resample_to_channels; j++)
+		{
+			memcpy(*out + (i * resample_to_channels * samplewidth) + (samplewidth * j),
+			       in + (source * resample_to_channels * samplewidth) +
+			       (samplewidth * j), samplewidth);
+		}
+#endif
+	}
+	outsize = i * resample_to_channels * samplewidth;
+#endif
+
+	if (tmpdata != NULL)
+		xfree(tmpdata);
+
+	/* Shrink 16bit output-samples to 8bit */
+#ifndef HAVE_LIBSAMPLERATE	/* libsamplerate produces 16bit samples */
+	if (format->wBitsPerSample != resample_to_bitspersample)
+#endif
+	{
+		/* source: 16 bit, dest: 8 bit */
+		if (resample_to_bitspersample == 8)
+		{
+			for (i = 0; i < outsize; i++)
+			{
+				*out[i] = *out[i * 2];
+			}
+			outsize /= 2;
+		}
+	}
+
+#ifdef B_ENDIAN
+	if (!stream_be)
+		rdpsnd_dsp_swapbytes(*out, outsize, format);
+#endif
+	return outsize;
+}
+
+STREAM
+rdpsnd_dsp_process(unsigned char *data, unsigned int size, struct audio_driver * current_driver,
+		   RD_WAVEFORMATEX * format)
+{
+	static struct stream out;
+	RD_BOOL stream_be = False;
+
+	/* softvol and byteswap do not change the amount of data they
+	   return, so they can operate on the input-stream */
+	if (current_driver->wave_out_volume == rdpsnd_dsp_softvol_set)
+		rdpsnd_dsp_softvol(data, size, format);
+
+#ifdef B_ENDIAN
+	if (current_driver->need_byteswap_on_be)
+	{
+		rdpsnd_dsp_swapbytes(data, size, format);
+		stream_be = True;
+	}
+#endif
+
+	out.data = NULL;
+
+	if (current_driver->need_resampling)
+		out.size = rdpsnd_dsp_resample(&out.data, data, size, format, stream_be);
+
+	if (out.data == NULL)
+	{
+		out.data = (unsigned char *) xmalloc(size);
+		memcpy(out.data, data, size);
+		out.size = size;
+	}
+
+	out.p = out.data;
+	out.end = out.p + out.size;
+
+	return &out;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_dsp.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_dsp.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_dsp.h	(revision 55121)
@@ -0,0 +1,32 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   Sound DSP routines
+   Copyright (C) Michael Gernoth 2006-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* Software volume control */
+void rdpsnd_dsp_softvol_set(uint16 left, uint16 right);
+
+/* Endian conversion */
+void rdpsnd_dsp_swapbytes(unsigned char *buffer, unsigned int size, RD_WAVEFORMATEX * format);
+
+/* Resample control */
+RD_BOOL rdpsnd_dsp_resample_set(uint32 device_srate, uint16 device_bitspersample,
+				uint16 device_channels);
+RD_BOOL rdpsnd_dsp_resample_supported(RD_WAVEFORMATEX * pwfx);
+
+STREAM rdpsnd_dsp_process(unsigned char *data, unsigned int size,
+			  struct audio_driver *current_driver, RD_WAVEFORMATEX * format);
Index: /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_libao.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_libao.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_libao.c	(revision 55121)
@@ -0,0 +1,226 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Sound Channel Process Functions - libao-driver
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
+   Copyright (C) GuoJunBo <guojunbo@ict.ac.cn> 2003
+   Copyright (C) Michael Gernoth <mike@zerfleddert.de> 2005-2008
+   Copyright (C) 2013 Henrik Andersson
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+#include "rdpsnd.h"
+#include "rdpsnd_dsp.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ao/ao.h>
+#include <sys/time.h>
+
+#define WAVEOUTLEN	16
+
+static ao_device *o_device = NULL;
+static int default_driver;
+static RD_BOOL reopened;
+static char *libao_device = NULL;
+
+void libao_play(void);
+
+void
+libao_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
+{
+	/* We need to be called rather often... */
+	if (o_device != NULL && !rdpsnd_queue_empty())
+		FD_SET(0, wfds);
+}
+
+void
+libao_check_fds(fd_set * rfds, fd_set * wfds)
+{
+	if (o_device == NULL)
+		return;
+
+	if (!rdpsnd_queue_empty())
+		libao_play();
+}
+
+RD_BOOL
+libao_open(void)
+{
+	ao_sample_format format;
+
+	ao_initialize();
+
+	if (libao_device)
+	{
+		default_driver = ao_driver_id(libao_device);
+	}
+	else
+	{
+		default_driver = ao_default_driver_id();
+	}
+
+	memset(&format, 0, sizeof(format));
+	format.bits = 16;
+	format.channels = 2;
+	format.rate = 44100;
+	format.byte_format = AO_FMT_NATIVE;
+
+	o_device = ao_open_live(default_driver, &format, NULL);
+	if (o_device == NULL)
+	{
+		return False;
+	}
+
+	reopened = True;
+
+	return True;
+}
+
+void
+libao_close(void)
+{
+	/* Ack all remaining packets */
+	while (!rdpsnd_queue_empty())
+	{
+		rdpsnd_queue_next(0);
+	}
+
+	if (o_device != NULL)
+		ao_close(o_device);
+
+	o_device = NULL;
+
+	ao_shutdown();
+}
+
+RD_BOOL
+libao_set_format(RD_WAVEFORMATEX * pwfx)
+{
+	ao_sample_format format;
+
+	memset(&format, 0, sizeof(format));
+	format.bits = pwfx->wBitsPerSample;
+	format.channels = pwfx->nChannels;
+	format.rate = 44100;
+	format.byte_format = AO_FMT_NATIVE;
+
+	if (o_device != NULL)
+		ao_close(o_device);
+
+	o_device = ao_open_live(default_driver, &format, NULL);
+	if (o_device == NULL)
+	{
+		return False;
+	}
+
+	if (rdpsnd_dsp_resample_set(44100, pwfx->wBitsPerSample, pwfx->nChannels) == False)
+	{
+		return False;
+	}
+
+	reopened = True;
+
+	return True;
+}
+
+void
+libao_play(void)
+{
+	struct audio_packet *packet;
+	STREAM out;
+	int len;
+	static long prev_s, prev_us;
+	unsigned int duration;
+	struct timeval tv;
+	int next_tick;
+
+	if (reopened)
+	{
+		reopened = False;
+		gettimeofday(&tv, NULL);
+		prev_s = tv.tv_sec;
+		prev_us = tv.tv_usec;
+	}
+
+	/* We shouldn't be called if the queue is empty, but still */
+	if (rdpsnd_queue_empty())
+		return;
+
+	packet = rdpsnd_queue_current_packet();
+	out = &packet->s;
+
+	next_tick = rdpsnd_queue_next_tick();
+
+	len = (WAVEOUTLEN > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTLEN;
+	ao_play(o_device, (char *) out->p, len);
+	out->p += len;
+
+	gettimeofday(&tv, NULL);
+
+	duration = ((tv.tv_sec - prev_s) * 1000000 + (tv.tv_usec - prev_us)) / 1000;
+
+	if (packet->tick > next_tick)
+		next_tick += 65536;
+
+	if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
+	{
+		unsigned int delay_us;
+
+		prev_s = tv.tv_sec;
+		prev_us = tv.tv_usec;
+
+		if (abs((next_tick - packet->tick) - duration) > 20)
+		{
+			DEBUG(("duration: %d, calc: %d, ", duration, next_tick - packet->tick));
+			DEBUG(("last: %d, is: %d, should: %d\n", packet->tick,
+			       (packet->tick + duration) % 65536, next_tick % 65536));
+		}
+
+		delay_us = ((out->size / 4) * (1000000 / 44100));
+
+		rdpsnd_queue_next(delay_us);
+	}
+}
+
+struct audio_driver *
+libao_register(char *options)
+{
+	static struct audio_driver libao_driver;
+
+	memset(&libao_driver, 0, sizeof(libao_driver));
+
+	libao_driver.name = "libao";
+	libao_driver.description = "libao output driver, default device: system dependent";
+
+	libao_driver.add_fds = libao_add_fds;
+	libao_driver.check_fds = libao_check_fds;
+
+	libao_driver.wave_out_open = libao_open;
+	libao_driver.wave_out_close = libao_close;
+	libao_driver.wave_out_format_supported = rdpsnd_dsp_resample_supported;
+	libao_driver.wave_out_set_format = libao_set_format;
+	libao_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
+
+	libao_driver.need_byteswap_on_be = 1;
+	libao_driver.need_resampling = 1;
+
+	if (options)
+	{
+		libao_device = xstrdup(options);
+	}
+
+	return &libao_driver;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_oss.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_oss.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_oss.c	(revision 55121)
@@ -0,0 +1,528 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Sound Channel Process Functions - Open Sound System
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
+   Copyright (C) GuoJunBo <guojunbo@ict.ac.cn> 2003
+   Copyright 2006-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
+   Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* 
+   This is a workaround for Esound bug 312665. 
+   FIXME: Remove this when Esound is fixed. 
+*/
+#ifdef _FILE_OFFSET_BITS
+#undef _FILE_OFFSET_BITS
+#endif
+
+#include <assert.h>
+
+#include "rdesktop.h"
+#include "rdpsnd.h"
+#include "rdpsnd_dsp.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define DEFAULTDEVICE	"/dev/dsp"
+#define MAX_LEN		512
+
+static int dsp_fd = -1;
+static int dsp_mode;
+
+static RD_BOOL dsp_configured;
+static RD_BOOL dsp_broken;
+
+static int stereo;
+static int format;
+static uint32 snd_rate;
+static short samplewidth;
+static char *dsp_dev;
+static RD_BOOL in_esddsp;
+
+/* This is a just a forward declaration */
+static struct audio_driver oss_driver;
+
+static void oss_play(void);
+static void oss_record(void);
+static RD_BOOL oss_set_format(RD_WAVEFORMATEX * pwfx);
+
+static void
+oss_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
+{
+	if (dsp_fd == -1)
+		return;
+
+	if ((dsp_mode == O_WRONLY || dsp_mode == O_RDWR) && !rdpsnd_queue_empty())
+		FD_SET(dsp_fd, wfds);
+	if (dsp_mode == O_RDONLY || dsp_mode == O_RDWR)
+		FD_SET(dsp_fd, rfds);
+	if (dsp_fd > *n)
+		*n = dsp_fd;
+}
+
+static void
+oss_check_fds(fd_set * rfds, fd_set * wfds)
+{
+	if (FD_ISSET(dsp_fd, wfds))
+		oss_play();
+	if (FD_ISSET(dsp_fd, rfds))
+		oss_record();
+}
+
+static RD_BOOL
+detect_esddsp(void)
+{
+	struct stat s;
+	char *preload;
+
+	if (fstat(dsp_fd, &s) == -1)
+		return False;
+
+	if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
+		return False;
+
+	preload = getenv("LD_PRELOAD");
+	if (preload == NULL)
+		return False;
+
+	if (strstr(preload, "esddsp") == NULL)
+		return False;
+
+	return True;
+}
+
+
+static void
+oss_restore_format()
+{
+	RD_WAVEFORMATEX wfx;
+	memset(&wfx, 0, sizeof(RD_WAVEFORMATEX));
+	switch (format)
+	{
+		case AFMT_U8:
+			wfx.wBitsPerSample = 8;
+			break;
+		case AFMT_S16_LE:
+			wfx.wBitsPerSample = 16;
+			break;
+		default:
+			wfx.wBitsPerSample = 0;
+	}
+	wfx.nChannels = stereo ? 2 : 1;
+	wfx.nSamplesPerSec = snd_rate;
+	oss_set_format(&wfx);
+}
+
+
+static RD_BOOL
+oss_open(int wanted)
+{
+	if (dsp_fd != -1)
+	{
+		if (wanted == dsp_mode)
+		{
+			/* should probably not happen */
+			return True;
+		}
+		else
+		{
+			/* device open but not our mode. Before
+			   reopening O_RDWR, verify that the device is
+			   duplex capable */
+			int caps;
+			ioctl(dsp_fd, SNDCTL_DSP_SETDUPLEX, 0);
+			if ((ioctl(dsp_fd, SNDCTL_DSP_GETCAPS, &caps) < 0)
+			    || !(caps & DSP_CAP_DUPLEX))
+			{
+				warning("This device is not capable of full duplex operation.\n");
+				return False;
+			}
+			close(dsp_fd);
+			dsp_mode = O_RDWR;
+		}
+	}
+	else
+	{
+		dsp_mode = wanted;
+	}
+
+	dsp_configured = False;
+	dsp_broken = False;
+
+	dsp_fd = open(dsp_dev, dsp_mode | O_NONBLOCK);
+
+	if (dsp_fd == -1)
+	{
+		perror(dsp_dev);
+		return False;
+	}
+
+	in_esddsp = detect_esddsp();
+
+	return True;
+}
+
+static void
+oss_close(void)
+{
+	close(dsp_fd);
+	dsp_fd = -1;
+}
+
+static RD_BOOL
+oss_open_out(void)
+{
+	if (!oss_open(O_WRONLY))
+		return False;
+
+	return True;
+}
+
+static void
+oss_close_out(void)
+{
+	oss_close();
+	if (dsp_mode == O_RDWR)
+	{
+		if (oss_open(O_RDONLY))
+			oss_restore_format();
+	}
+
+	/* Ack all remaining packets */
+	while (!rdpsnd_queue_empty())
+		rdpsnd_queue_next(0);
+}
+
+static RD_BOOL
+oss_open_in(void)
+{
+	if (!oss_open(O_RDONLY))
+		return False;
+
+	return True;
+}
+
+static void
+oss_close_in(void)
+{
+	oss_close();
+	if (dsp_mode == O_RDWR)
+	{
+		if (oss_open(O_WRONLY))
+			oss_restore_format();
+	}
+}
+
+static RD_BOOL
+oss_format_supported(RD_WAVEFORMATEX * pwfx)
+{
+	if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
+		return False;
+	if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
+		return False;
+	if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
+		return False;
+
+	return True;
+}
+
+static RD_BOOL
+oss_set_format(RD_WAVEFORMATEX * pwfx)
+{
+	int fragments;
+	static RD_BOOL driver_broken = False;
+
+	assert(dsp_fd != -1);
+
+	if (dsp_configured)
+	{
+		if ((pwfx->wBitsPerSample == 8) && (format != AFMT_U8))
+			return False;
+		if ((pwfx->wBitsPerSample == 16) && (format != AFMT_S16_LE))
+			return False;
+
+		if ((pwfx->nChannels == 2) != ! !stereo)
+			return False;
+
+		if (pwfx->nSamplesPerSec != snd_rate)
+			return False;
+
+		return True;
+	}
+
+	ioctl(dsp_fd, SNDCTL_DSP_RESET, NULL);
+	ioctl(dsp_fd, SNDCTL_DSP_SYNC, NULL);
+
+	if (pwfx->wBitsPerSample == 8)
+		format = AFMT_U8;
+	else if (pwfx->wBitsPerSample == 16)
+		format = AFMT_S16_LE;
+
+	samplewidth = pwfx->wBitsPerSample / 8;
+
+	if (ioctl(dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
+	{
+		perror("SNDCTL_DSP_SETFMT");
+		oss_close();
+		return False;
+	}
+
+	if (pwfx->nChannels == 2)
+	{
+		stereo = 1;
+		samplewidth *= 2;
+	}
+	else
+	{
+		stereo = 0;
+	}
+
+	if (ioctl(dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
+	{
+		perror("SNDCTL_DSP_CHANNELS");
+		oss_close();
+		return False;
+	}
+
+	oss_driver.need_resampling = 0;
+	snd_rate = pwfx->nSamplesPerSec;
+	if (ioctl(dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)
+	{
+		uint32 rates[] = { 44100, 48000, 0 };
+		uint32 *prates = rates;
+
+		while (*prates != 0)
+		{
+			if ((pwfx->nSamplesPerSec != *prates)
+			    && (ioctl(dsp_fd, SNDCTL_DSP_SPEED, prates) != -1))
+			{
+				oss_driver.need_resampling = 1;
+				snd_rate = *prates;
+				if (rdpsnd_dsp_resample_set
+				    (snd_rate, pwfx->wBitsPerSample, pwfx->nChannels) == False)
+				{
+					error("rdpsnd_dsp_resample_set failed");
+					oss_close();
+					return False;
+				}
+
+				break;
+			}
+			prates++;
+		}
+
+		if (*prates == 0)
+		{
+			perror("SNDCTL_DSP_SPEED");
+			oss_close();
+			return False;
+		}
+	}
+
+	/* try to get 12 fragments of 2^12 bytes size */
+	fragments = (12 << 16) + 12;
+	ioctl(dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
+
+	if (!driver_broken)
+	{
+		audio_buf_info info;
+
+		memset(&info, 0, sizeof(info));
+		if (ioctl(dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
+		{
+			perror("SNDCTL_DSP_GETOSPACE");
+			oss_close();
+			return False;
+		}
+
+		if (info.fragments == 0 || info.fragstotal == 0 || info.fragsize == 0)
+		{
+			fprintf(stderr,
+				"Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",
+				info.fragments, info.fragstotal, info.fragsize);
+			driver_broken = True;
+		}
+	}
+
+	dsp_configured = True;
+
+	return True;
+}
+
+static void
+oss_volume(uint16 left, uint16 right)
+{
+	uint32 volume;
+
+	volume = left / (65536 / 100);
+	volume |= right / (65536 / 100) << 8;
+
+	if (ioctl(dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
+	{
+		warning("hardware volume control unavailable, falling back to software volume control!\n");
+		oss_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
+		rdpsnd_dsp_softvol_set(left, right);
+		return;
+	}
+}
+
+static void
+oss_play(void)
+{
+	struct audio_packet *packet;
+	ssize_t len;
+	STREAM out;
+
+	assert(dsp_fd != -1);
+
+	/* We shouldn't be called if the queue is empty, but still */
+	if (rdpsnd_queue_empty())
+		return;
+
+	packet = rdpsnd_queue_current_packet();
+	out = &packet->s;
+
+	len = out->end - out->p;
+
+	len = write(dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
+	if (len == -1)
+	{
+		if (errno != EWOULDBLOCK)
+		{
+			if (!dsp_broken)
+				perror("RDPSND: write()");
+			dsp_broken = True;
+			rdpsnd_queue_next(0);
+		}
+		return;
+	}
+
+	dsp_broken = False;
+
+	out->p += len;
+
+	if (out->p == out->end)
+	{
+		int delay_bytes;
+		unsigned long delay_us;
+		audio_buf_info info;
+
+		if (in_esddsp)
+		{
+			/* EsounD has no way of querying buffer status, so we have to
+			 * go with a fixed size. */
+			delay_bytes = out->size;
+		}
+		else
+		{
+#ifdef SNDCTL_DSP_GETODELAY
+			delay_bytes = 0;
+			if (ioctl(dsp_fd, SNDCTL_DSP_GETODELAY, &delay_bytes) == -1)
+				delay_bytes = -1;
+#else
+			delay_bytes = -1;
+#endif
+
+			if (delay_bytes == -1)
+			{
+				if (ioctl(dsp_fd, SNDCTL_DSP_GETOSPACE, &info) != -1)
+					delay_bytes = info.fragstotal * info.fragsize - info.bytes;
+				else
+					delay_bytes = out->size;
+			}
+		}
+
+		delay_us = delay_bytes * (1000000 / (samplewidth * snd_rate));
+		rdpsnd_queue_next(delay_us);
+	}
+}
+
+static void
+oss_record(void)
+{
+	char buffer[32768];
+	int len;
+
+	assert(dsp_fd != -1);
+
+	len = read(dsp_fd, buffer, sizeof(buffer));
+	if (len == -1)
+	{
+		if (errno != EWOULDBLOCK)
+		{
+			if (!dsp_broken)
+				perror("RDPSND: read()");
+			dsp_broken = True;
+			rdpsnd_queue_next(0);
+		}
+		return;
+	}
+
+	dsp_broken = False;
+
+	rdpsnd_record(buffer, len);
+}
+
+struct audio_driver *
+oss_register(char *options)
+{
+	memset(&oss_driver, 0, sizeof(oss_driver));
+
+	oss_driver.name = "oss";
+	oss_driver.description =
+		"OSS output driver, default device: " DEFAULTDEVICE " or $AUDIODEV";
+
+	oss_driver.add_fds = oss_add_fds;
+	oss_driver.check_fds = oss_check_fds;
+
+	oss_driver.wave_out_open = oss_open_out;
+	oss_driver.wave_out_close = oss_close_out;
+	oss_driver.wave_out_format_supported = oss_format_supported;
+	oss_driver.wave_out_set_format = oss_set_format;
+	oss_driver.wave_out_volume = oss_volume;
+
+	oss_driver.wave_in_open = oss_open_in;
+	oss_driver.wave_in_close = oss_close_in;
+	oss_driver.wave_in_format_supported = oss_format_supported;
+	oss_driver.wave_in_set_format = oss_set_format;
+	oss_driver.wave_in_volume = NULL;	/* FIXME */
+
+	oss_driver.need_byteswap_on_be = 0;
+	oss_driver.need_resampling = 0;
+
+	if (options)
+	{
+		dsp_dev = xstrdup(options);
+	}
+	else
+	{
+		dsp_dev = getenv("AUDIODEV");
+
+		if (dsp_dev == NULL)
+		{
+			dsp_dev = DEFAULTDEVICE;
+		}
+	}
+
+	return &oss_driver;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_sgi.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_sgi.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_sgi.c	(revision 55121)
@@ -0,0 +1,319 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Sound Channel Process Functions - SGI/IRIX
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
+   Copyright (C) GuoJunBo <guojunbo@ict.ac.cn> 2003
+   Copyright (C) Jeremy Meng <void.foo@gmail.com> 2004-2005
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+#include <errno.h>
+#include <dmedia/audio.h>
+
+/* #define IRIX_DEBUG 1 */
+
+#define IRIX_MAX_VOL     65535
+
+ALconfig audioconfig;
+ALport output_port;
+
+static int g_snd_rate;
+static int width = AL_SAMPLE_16;
+static char *sgi_output_device = NULL;
+
+double min_volume, max_volume, volume_range;
+int resource, maxFillable;
+int combinedFrameSize;
+
+void sgi_play(void);
+
+void
+sgi_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
+{
+	/* We need to be called rather often... */
+	if (output_port != (ALport) 0 && !rdpsnd_queue_empty())
+		FD_SET(0, wfds);
+}
+
+void
+sgi_check_fds(fd_set * rfds, fd_set * wfds)
+{
+	if (output_port == (ALport) 0)
+		return;
+
+	if (!rdpsnd_queue_empty())
+		sgi_play();
+}
+
+RD_BOOL
+sgi_open(void)
+{
+	ALparamInfo pinfo;
+	static int warned = 0;
+
+#if (defined(IRIX_DEBUG))
+	fprintf(stderr, "sgi_open: begin\n");
+#endif
+
+	if (!warned && sgi_output_device)
+	{
+		warning("device-options not supported for libao-driver\n");
+		warned = 1;
+	}
+
+	if (alGetParamInfo(AL_DEFAULT_OUTPUT, AL_GAIN, &pinfo) < 0)
+	{
+		fprintf(stderr, "sgi_open: alGetParamInfo failed: %s\n",
+			alGetErrorString(oserror()));
+	}
+	min_volume = alFixedToDouble(pinfo.min.ll);
+	max_volume = alFixedToDouble(pinfo.max.ll);
+	volume_range = (max_volume - min_volume);
+#if (defined(IRIX_DEBUG))
+	fprintf(stderr, "sgi_open: minvol = %lf, maxvol= %lf, range = %lf.\n",
+		min_volume, max_volume, volume_range);
+#endif
+
+	audioconfig = alNewConfig();
+	if (audioconfig == (ALconfig) 0)
+	{
+		fprintf(stderr, "sgi_open: alNewConfig failed: %s\n", alGetErrorString(oserror()));
+		return False;
+	}
+
+	output_port = alOpenPort("rdpsnd", "w", 0);
+	if (output_port == (ALport) 0)
+	{
+		fprintf(stderr, "sgi_open: alOpenPort failed: %s\n", alGetErrorString(oserror()));
+		return False;
+	}
+
+#if (defined(IRIX_DEBUG))
+	fprintf(stderr, "sgi_open: returning\n");
+#endif
+	return True;
+}
+
+void
+sgi_close(void)
+{
+	/* Ack all remaining packets */
+#if (defined(IRIX_DEBUG))
+	fprintf(stderr, "sgi_close: begin\n");
+#endif
+
+	while (!rdpsnd_queue_empty())
+		rdpsnd_queue_next(0);
+	alDiscardFrames(output_port, 0);
+
+	alClosePort(output_port);
+	output_port = (ALport) 0;
+	alFreeConfig(audioconfig);
+#if (defined(IRIX_DEBUG))
+	fprintf(stderr, "sgi_close: returning\n");
+#endif
+}
+
+RD_BOOL
+sgi_format_supported(RD_WAVEFORMATEX * pwfx)
+{
+	if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
+		return False;
+	if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
+		return False;
+	if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
+		return False;
+
+	return True;
+}
+
+RD_BOOL
+sgi_set_format(RD_WAVEFORMATEX * pwfx)
+{
+	int channels;
+	int frameSize, channelCount;
+	ALpv params;
+
+#if (defined(IRIX_DEBUG))
+	fprintf(stderr, "sgi_set_format: init...\n");
+#endif
+
+	if (pwfx->wBitsPerSample == 8)
+		width = AL_SAMPLE_8;
+	else if (pwfx->wBitsPerSample == 16)
+		width = AL_SAMPLE_16;
+
+	/* Limited support to configure an opened audio port in IRIX.  The
+	   number of channels is a static setting and can not be changed after
+	   a port is opened.  So if the number of channels remains the same, we
+	   can configure other settings; otherwise we have to reopen the audio
+	   port, using same config. */
+
+	channels = pwfx->nChannels;
+	g_snd_rate = pwfx->nSamplesPerSec;
+
+	alSetSampFmt(audioconfig, AL_SAMPFMT_TWOSCOMP);
+	alSetWidth(audioconfig, width);
+	if (channels != alGetChannels(audioconfig))
+	{
+		alClosePort(output_port);
+		alSetChannels(audioconfig, channels);
+		output_port = alOpenPort("rdpsnd", "w", audioconfig);
+
+		if (output_port == (ALport) 0)
+		{
+			fprintf(stderr, "sgi_set_format: alOpenPort failed: %s\n",
+				alGetErrorString(oserror()));
+			return False;
+		}
+
+	}
+
+	resource = alGetResource(output_port);
+	maxFillable = alGetFillable(output_port);
+	channelCount = alGetChannels(audioconfig);
+	frameSize = alGetWidth(audioconfig);
+
+	if (frameSize == 0 || channelCount == 0)
+	{
+		fprintf(stderr, "sgi_set_format: bad frameSize or channelCount\n");
+		return False;
+	}
+	combinedFrameSize = frameSize * channelCount;
+
+	params.param = AL_RATE;
+	params.value.ll = (long long) g_snd_rate << 32;
+
+	if (alSetParams(resource, &params, 1) < 0)
+	{
+		fprintf(stderr, "wave_set_format: alSetParams failed: %s\n",
+			alGetErrorString(oserror()));
+		return False;
+	}
+	if (params.sizeOut < 0)
+	{
+		fprintf(stderr, "wave_set_format: invalid rate %d\n", g_snd_rate);
+		return False;
+	}
+
+#if (defined(IRIX_DEBUG))
+	fprintf(stderr, "sgi_set_format: returning...\n");
+#endif
+	return True;
+}
+
+void
+sgi_volume(uint16 left, uint16 right)
+{
+	double gainleft, gainright;
+	ALpv pv[1];
+	ALfixed gain[8];
+
+#if (defined(IRIX_DEBUG))
+	fprintf(stderr, "sgi_volume: begin\n");
+	fprintf(stderr, "left='%d', right='%d'\n", left, right);
+#endif
+
+	gainleft = (double) left / IRIX_MAX_VOL;
+	gainright = (double) right / IRIX_MAX_VOL;
+
+	gain[0] = alDoubleToFixed(min_volume + gainleft * volume_range);
+	gain[1] = alDoubleToFixed(min_volume + gainright * volume_range);
+
+	pv[0].param = AL_GAIN;
+	pv[0].value.ptr = gain;
+	pv[0].sizeIn = 8;
+	if (alSetParams(AL_DEFAULT_OUTPUT, pv, 1) < 0)
+	{
+		fprintf(stderr, "sgi_volume: alSetParams failed: %s\n",
+			alGetErrorString(oserror()));
+		return;
+	}
+
+#if (defined(IRIX_DEBUG))
+	fprintf(stderr, "sgi_volume: returning\n");
+#endif
+}
+
+void
+sgi_play(void)
+{
+	struct audio_packet *packet;
+	ssize_t len;
+	unsigned int i;
+	STREAM out;
+	int gf;
+
+	while (1)
+	{
+		if (rdpsnd_queue_empty())
+			return;
+
+		packet = rdpsnd_queue_current_packet();
+		out = &packet->s;
+
+		len = out->end - out->p;
+
+		alWriteFrames(output_port, out->p, len / combinedFrameSize);
+
+		out->p += len;
+		if (out->p == out->end)
+		{
+			gf = alGetFilled(output_port);
+			if (gf < (4 * maxFillable / 10))
+			{
+				rdpsnd_queue_next(0);
+			}
+			else
+			{
+#if (defined(IRIX_DEBUG))
+/*  				fprintf(stderr,"Busy playing...\n"); */
+#endif
+				usleep(10);
+				return;
+			}
+		}
+	}
+}
+
+struct audio_driver *
+sgi_register(char *options)
+{
+	static struct audio_driver sgi_driver;
+
+	memset(&sgi_driver, 0, sizeof(sgi_driver));
+
+	sgi_driver.name = "sgi";
+	sgi_driver.description = "SGI output driver";
+
+	sgi_driver.add_fds = sgi_add_fds;
+	sgi_driver.check_fds = sgi_check_fds;
+
+	sgi_driver.wave_out_open = sgi_open;
+	sgi_driver.wave_out_close = sgi_close;
+	sgi_driver.wave_out_format_supported = sgi_format_supported;
+	sgi_driver.wave_out_set_format = sgi_set_format;
+	sgi_driver.wave_out_volume = sgi_volume;
+
+	sgi_driver.need_byteswap_on_be = 1;
+	sgi_driver.need_resampling = 0;
+
+	if (options)
+	{
+		sgi_output_device = xstrdup(options);
+	}
+	return &sgi_driver;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_sun.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_sun.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/rdpsnd_sun.c	(revision 55121)
@@ -0,0 +1,539 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Sound Channel Process Functions - Sun
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
+   Copyright (C) GuoJunBo <guojunbo@ict.ac.cn> 2003
+   Copyright (C) Michael Gernoth <mike@zerfleddert.de> 2003-2008
+   Copyright 2007-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
+   Copyright 2008-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+#include "rdpsnd.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/audioio.h>
+#include <string.h>
+
+#if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
+#include <stropts.h>
+#endif
+
+#define DEFAULTDEVICE	"/dev/audio"
+#define MAX_LEN		512
+
+static int dsp_fd = -1;
+static int dsp_mode;
+static int dsp_refs;
+
+static RD_BOOL dsp_configured;
+static RD_BOOL dsp_broken;
+static RD_BOOL broken_2_channel_record = False;
+
+static RD_BOOL dsp_out;
+static RD_BOOL dsp_in;
+
+static int stereo;
+static int format;
+static uint32 snd_rate;
+static short samplewidth;
+static char *dsp_dev;
+
+static uint_t written_samples;
+
+void sun_play(void);
+void sun_record(void);
+
+static int
+sun_pause(void)
+{
+	audio_info_t info;
+
+	AUDIO_INITINFO(&info);
+
+	info.record.pause = 1;
+
+	if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
+		return -1;
+
+#if defined I_FLUSH && defined FLUSHR
+	if (ioctl(dsp_fd, I_FLUSH, FLUSHR) == -1)
+		return -1;
+#endif
+
+	return 0;
+}
+
+static int
+sun_resume(void)
+{
+	audio_info_t info;
+
+	AUDIO_INITINFO(&info);
+
+	info.record.pause = 0;
+
+	if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
+		return -1;
+
+	return 0;
+}
+
+void
+sun_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
+{
+	if (dsp_fd == -1)
+		return;
+
+	if (dsp_out && !rdpsnd_queue_empty())
+		FD_SET(dsp_fd, wfds);
+	if (dsp_in)
+		FD_SET(dsp_fd, rfds);
+	if (dsp_fd > *n)
+		*n = dsp_fd;
+}
+
+void
+sun_check_fds(fd_set * rfds, fd_set * wfds)
+{
+	if (FD_ISSET(dsp_fd, wfds))
+		sun_play();
+	if (FD_ISSET(dsp_fd, rfds))
+		sun_record();
+}
+
+RD_BOOL
+sun_open(int mode)
+{
+	audio_info_t info;
+
+	if (dsp_fd != -1)
+	{
+		dsp_refs++;
+
+		if (dsp_mode == O_RDWR)
+			return True;
+
+		if (dsp_mode == mode)
+			return True;
+
+		dsp_refs--;
+		return False;
+	}
+
+	dsp_configured = False;
+	dsp_broken = False;
+
+	written_samples = 0;
+
+	dsp_mode = O_RDWR;
+	dsp_fd = open(dsp_dev, O_RDWR | O_NONBLOCK);
+	if (dsp_fd != -1)
+	{
+		AUDIO_INITINFO(&info);
+
+		if ((ioctl(dsp_fd, AUDIO_GETINFO, &info) == -1)
+		    || !(info.hw_features & AUDIO_HWFEATURE_DUPLEX))
+		{
+			close(dsp_fd);
+			dsp_fd = -1;
+		}
+	}
+
+	if (dsp_fd == -1)
+	{
+		dsp_mode = mode;
+
+		dsp_fd = open(dsp_dev, dsp_mode | O_NONBLOCK);
+		if (dsp_fd == -1)
+		{
+			perror(dsp_dev);
+			return False;
+		}
+	}
+
+	/*
+	 * Pause recording until we actually start using it.
+	 */
+	if (dsp_mode != O_WRONLY)
+	{
+		if (sun_pause() == -1)
+		{
+			close(dsp_fd);
+			dsp_fd = -1;
+			return False;
+		}
+	}
+
+	dsp_refs++;
+
+	return True;
+}
+
+void
+sun_close(void)
+{
+	dsp_refs--;
+
+	if (dsp_refs != 0)
+		return;
+
+	close(dsp_fd);
+	dsp_fd = -1;
+}
+
+RD_BOOL
+sun_open_out(void)
+{
+	if (!sun_open(O_WRONLY))
+		return False;
+
+	dsp_out = True;
+
+	return True;
+}
+
+void
+sun_close_out(void)
+{
+#if defined I_FLUSH && defined FLUSHW
+	/* Flush the audiobuffer */
+	ioctl(dsp_fd, I_FLUSH, FLUSHW);
+#endif
+#if defined AUDIO_FLUSH
+	ioctl(dsp_fd, AUDIO_FLUSH, NULL);
+#endif
+
+	sun_close();
+
+	/* Ack all remaining packets */
+	while (!rdpsnd_queue_empty())
+		rdpsnd_queue_next(0);
+
+	dsp_out = False;
+}
+
+RD_BOOL
+sun_open_in(void)
+{
+#if ! (defined I_FLUSH && defined FLUSHR)
+	/*
+	 * It is not possible to reliably use the recording without
+	 * flush operations.
+	 */
+	return False;
+#endif
+
+	if (!sun_open(O_RDONLY))
+		return False;
+
+	/* 2 channel recording is known to be broken on Solaris x86
+	   Sun Ray systems */
+#ifdef L_ENDIAN
+	if (strstr(dsp_dev, "/utaudio/"))
+		broken_2_channel_record = True;
+#endif
+
+	/*
+	 * Unpause the stream now that we have someone using it.
+	 */
+	if (sun_resume() == -1)
+	{
+		sun_close();
+		return False;
+	}
+
+	dsp_in = True;
+
+	return True;
+}
+
+void
+sun_close_in(void)
+{
+	/*
+	 * Repause the stream when the user goes away.
+	 */
+	sun_pause();
+
+	sun_close();
+
+	dsp_in = False;
+}
+
+RD_BOOL
+sun_format_supported(RD_WAVEFORMATEX * pwfx)
+{
+	if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
+		return False;
+	if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
+		return False;
+	if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
+		return False;
+
+	return True;
+}
+
+RD_BOOL
+sun_set_format(RD_WAVEFORMATEX * pwfx)
+{
+	audio_info_t info;
+
+	ioctl(dsp_fd, AUDIO_DRAIN, 0);
+	AUDIO_INITINFO(&info);
+
+	if (dsp_configured)
+	{
+		if ((pwfx->wBitsPerSample == 8) && (format != AUDIO_ENCODING_LINEAR8))
+			return False;
+		if ((pwfx->wBitsPerSample == 16) && (format != AUDIO_ENCODING_LINEAR))
+			return False;
+
+		if ((pwfx->nChannels == 2) != ! !stereo)
+			return False;
+
+		if (pwfx->nSamplesPerSec != snd_rate)
+			return False;
+
+		return True;
+	}
+
+	sun_pause();
+
+	if (pwfx->wBitsPerSample == 8)
+		format = AUDIO_ENCODING_LINEAR8;
+	else if (pwfx->wBitsPerSample == 16)
+		format = AUDIO_ENCODING_LINEAR;
+
+	samplewidth = pwfx->wBitsPerSample / 8;
+
+	info.play.channels = pwfx->nChannels;
+	info.record.channels = info.play.channels;
+
+	if (pwfx->nChannels == 1)
+	{
+		stereo = 0;
+	}
+	else if (pwfx->nChannels == 2)
+	{
+		stereo = 1;
+		samplewidth *= 2;
+
+		if (broken_2_channel_record)
+		{
+			info.record.channels = 1;
+		}
+	}
+
+	snd_rate = pwfx->nSamplesPerSec;
+
+	info.play.sample_rate = pwfx->nSamplesPerSec;
+	info.play.precision = pwfx->wBitsPerSample;
+	info.play.encoding = format;
+	info.play.samples = 0;
+	info.play.eof = 0;
+	info.play.error = 0;
+
+	info.record.sample_rate = info.play.sample_rate;
+	info.record.precision = info.play.precision;
+	info.record.encoding = info.play.encoding;
+	info.record.samples = 0;
+	info.record.error = 0;
+
+	if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
+	{
+		perror("AUDIO_SETINFO");
+		sun_close();
+		return False;
+	}
+
+	dsp_configured = True;
+
+	if (dsp_in)
+		sun_resume();
+
+	return True;
+}
+
+void
+sun_volume(uint16 left, uint16 right)
+{
+	audio_info_t info;
+	uint balance;
+	uint volume;
+
+	AUDIO_INITINFO(&info);
+
+	volume = (left > right) ? left : right;
+
+	if (volume / AUDIO_MID_BALANCE != 0)
+	{
+		balance =
+			AUDIO_MID_BALANCE - (left / (volume / AUDIO_MID_BALANCE)) +
+			(right / (volume / AUDIO_MID_BALANCE));
+	}
+	else
+	{
+		balance = AUDIO_MID_BALANCE;
+	}
+
+	info.play.gain = volume / (65536 / AUDIO_MAX_GAIN);
+	info.play.balance = balance;
+
+	if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
+	{
+		perror("AUDIO_SETINFO");
+		return;
+	}
+}
+
+void
+sun_play(void)
+{
+	struct audio_packet *packet;
+	ssize_t len;
+	STREAM out;
+
+	/* We shouldn't be called if the queue is empty, but still */
+	if (rdpsnd_queue_empty())
+		return;
+
+	packet = rdpsnd_queue_current_packet();
+	out = &packet->s;
+
+	len = out->end - out->p;
+
+	len = write(dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
+	if (len == -1)
+	{
+		if (errno != EWOULDBLOCK)
+		{
+			if (!dsp_broken)
+				perror("RDPSND: write()");
+			dsp_broken = True;
+			rdpsnd_queue_next(0);
+		}
+		return;
+	}
+
+	written_samples += len / (samplewidth * (stereo ? 2 : 1));
+
+	dsp_broken = False;
+
+	out->p += len;
+
+	if (out->p == out->end)
+	{
+		audio_info_t info;
+		uint_t delay_samples;
+		unsigned long delay_us;
+
+		if (ioctl(dsp_fd, AUDIO_GETINFO, &info) != -1)
+			delay_samples = written_samples - info.play.samples;
+		else
+			delay_samples = out->size / (samplewidth * (stereo ? 2 : 1));
+
+		delay_us = delay_samples * (1000000 / snd_rate);
+		rdpsnd_queue_next(delay_us);
+	}
+}
+
+void
+sun_record(void)
+{
+	char buffer[32768];
+	int len;
+
+	len = read(dsp_fd, buffer, sizeof(buffer) / 2);
+	if (len == -1)
+	{
+		if (errno != EWOULDBLOCK)
+			perror("read audio");
+		return;
+	}
+
+	if (broken_2_channel_record)
+	{
+		unsigned int i;
+		int rec_samplewidth = samplewidth / 2;
+		/* Loop over each byte read backwards and put in place */
+		i = len - 1;
+		do
+		{
+			int samples_before = i / rec_samplewidth * 2;
+			int sample_byte = i % rec_samplewidth;
+			int ch1_offset = samples_before * rec_samplewidth + sample_byte;
+			// Channel 1
+			buffer[ch1_offset] = buffer[i];
+			// Channel 2
+			buffer[ch1_offset + rec_samplewidth] = buffer[i];
+
+			i--;
+		}
+		while (i);
+		len *= 2;
+	}
+
+	rdpsnd_record(buffer, len);
+}
+
+struct audio_driver *
+sun_register(char *options)
+{
+	static struct audio_driver sun_driver;
+
+	memset(&sun_driver, 0, sizeof(sun_driver));
+
+	sun_driver.name = "sun";
+	sun_driver.description =
+		"SUN/BSD output driver, default device: " DEFAULTDEVICE " or $AUDIODEV";
+
+	sun_driver.add_fds = sun_add_fds;
+	sun_driver.check_fds = sun_check_fds;
+
+	sun_driver.wave_out_open = sun_open_out;
+	sun_driver.wave_out_close = sun_close_out;
+	sun_driver.wave_out_format_supported = sun_format_supported;
+	sun_driver.wave_out_set_format = sun_set_format;
+	sun_driver.wave_out_volume = sun_volume;
+
+	sun_driver.wave_in_open = sun_open_in;
+	sun_driver.wave_in_close = sun_close_in;
+	sun_driver.wave_in_format_supported = sun_format_supported;
+	sun_driver.wave_in_set_format = sun_set_format;
+	sun_driver.wave_in_volume = NULL;	/* FIXME */
+
+	sun_driver.need_byteswap_on_be = 1;
+	sun_driver.need_resampling = 0;
+
+	if (options)
+	{
+		dsp_dev = xstrdup(options);
+	}
+	else
+	{
+		dsp_dev = getenv("AUDIODEV");
+
+		if (dsp_dev == NULL)
+		{
+			dsp_dev = DEFAULTDEVICE;
+		}
+	}
+
+	return &sun_driver;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/scancodes.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/scancodes.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/scancodes.h	(revision 55121)
@@ -0,0 +1,376 @@
+
+/* Two defines for every scancode:
+   One called SCANCODE_KEY_<num>, where <num> is the key location number. 
+   One called SCANCODE_CHAR_<char-on-us-kbd>, where <char-on-us-kbd> is the 
+   unshifted character on a US 101/102 keyboard. See the Microsoft 
+   document "Keyboard Scan Code Specification" for more information. 
+
+   Up keys normally have scancode values +0x80. 
+
+   0x0: Avoid 
+   0x1- 0x59: Normal
+   0x60, 0x61: Avoid, since the up key would be 0xe1, 0xe1
+   0x61 - 0x79: Normal
+   0xfa - : keyboard drivers interpret these as responses from the 8042 chip
+
+   We use bit 7 to indicate 0xe0 prefix instead of two-byte sequence (0xe0, something). Eq.,
+   0xe 0x38 is defined as (0x80 | 0x38)
+*/
+
+/* FIXME: 
+   Special keys like Numeric / are very complicated and emits many scancodes. 
+*/
+
+#define SCANCODE_EXTENDED 0x80
+
+#define SCANCODE_KEY_1 0x29
+#define SCANCODE_CHAR_GRAVE 0x29
+
+#define SCANCODE_KEY_2 0x2
+#define SCANCODE_CHAR_1 SCANCODE_KEY_2
+
+#define SCANCODE_KEY_3 0x3
+#define SCANCODE_CHAR_2 SCANCODE_KEY_3
+
+#define SCANCODE_KEY_4 0x4
+#define SCANCODE_CHAR_3 SCANCODE_KEY_4
+
+#define SCANCODE_KEY_5 0x5
+#define SCANCODE_CHAR_4 SCANCODE_KEY_5
+
+#define SCANCODE_KEY_6 0x6
+#define SCANCODE_CHAR_5 SCANCODE_KEY_6
+
+#define SCANCODE_KEY_7 0x7
+#define SCANCODE_CHAR_6 SCANCODE_KEY_7
+
+#define SCANCODE_KEY_8 0x8
+#define SCANCODE_CHAR_7 SCANCODE_KEY_8
+
+#define SCANCODE_KEY_9 0x9
+#define SCANCODE_CHAR_8 SCANCODE_KEY_9
+
+#define SCANCODE_KEY_10 0xa
+#define SCANCODE_CHAR_9 SCANCODE_KEY_10
+
+#define SCANCODE_KEY_11 0xb
+#define SCANCODE_CHAR_0 SCANCODE_KEY_11
+
+#define SCANCODE_KEY_12 0xc
+#define SCANCODE_CHAR_MINUS SCANCODE_KEY_12
+
+#define SCANCODE_KEY_13 0xd
+#define SCANCODE_CHAR_EQUAL SCANCODE_KEY_13
+
+/* Key 14 does not exist */
+
+#define SCANCODE_KEY_15 0xe
+#define SCANCODE_CHAR_BACKSPACE SCANCODE_KEY_15
+
+#define SCANCODE_KEY_16 0xf
+#define SCANCODE_CHAR_TAB SCANCODE_KEY_16
+
+#define SCANCODE_KEY_17 0x10
+#define SCANCODE_CHAR_Q SCANCODE_KEY_17
+
+#define SCANCODE_KEY_18 0x11
+#define SCANCODE_CHAR_W SCANCODE_KEY_18
+
+#define SCANCODE_KEY_19 0x12
+#define SCANCODE_CHAR_E SCANCODE_KEY_19
+
+#define SCANCODE_KEY_20 0x13
+#define SCANCODE_CHAR_R SCANCODE_KEY_20
+
+#define SCANCODE_KEY_21 0x14
+#define SCANCODE_CHAR_T SCANCODE_KEY_21
+
+#define SCANCODE_KEY_22 0x15
+#define SCANCODE_CHAR_Y SCANCODE_KEY_22
+
+#define SCANCODE_KEY_23 0x16
+#define SCANCODE_CHAR_U SCANCODE_KEY_23
+
+#define SCANCODE_KEY_24 0x17
+#define SCANCODE_CHAR_I SCANCODE_KEY_24
+
+#define SCANCODE_KEY_25 0x18
+#define SCANCODE_CHAR_O SCANCODE_KEY_25
+
+#define SCANCODE_KEY_26 0x19
+#define SCANCODE_CHAR_P SCANCODE_KEY_26
+
+#define SCANCODE_KEY_27 0x1a
+#define SCANCODE_CHAR_BRACKETLEFT SCANCODE_KEY_27
+
+#define SCANCODE_KEY_28 0x1b
+#define SCANCODE_CHAR_BRACKETRIGHT SCANCODE_KEY_28
+
+/* Only on US keyboard */
+#define SCANCODE_KEY_29 0x2b
+#define SCANCODE_CHAR_BACKSLASH SCANCODE_KEY_29
+
+#define SCANCODE_KEY_30 0x3a
+#define SCANCODE_CHAR_CAPSLOCK SCANCODE_KEY_30
+
+#define SCANCODE_KEY_31 0x1e
+#define SCANCODE_CHAR_A SCANCODE_KEY_31
+
+#define SCANCODE_KEY_32 0x1f
+#define SCANCODE_CHAR_S SCANCODE_KEY_32
+
+#define SCANCODE_KEY_33 0x20
+#define SCANCODE_CHAR_D SCANCODE_KEY_33
+
+#define SCANCODE_KEY_34 0x21
+#define SCANCODE_CHAR_F SCANCODE_KEY_34
+
+#define SCANCODE_KEY_35 0x22
+#define SCANCODE_CHAR_G SCANCODE_KEY_35
+
+#define SCANCODE_KEY_36 0x23
+#define SCANCODE_CHAR_H SCANCODE_KEY_36
+
+#define SCANCODE_KEY_37 0x24
+#define SCANCODE_CHAR_J SCANCODE_KEY_37
+
+#define SCANCODE_KEY_38 0x25
+#define SCANCODE_CHAR_K SCANCODE_KEY_38
+
+#define SCANCODE_KEY_39 0x26
+#define SCANCODE_CHAR_L SCANCODE_KEY_39
+
+#define SCANCODE_KEY_40 0x27
+#define SCANCODE_CHAR_SEMICOLON SCANCODE_KEY_40
+
+#define SCANCODE_KEY_41 0x28
+#define SCANCODE_CHAR_APOSTROPHE SCANCODE_KEY_41
+
+/* Only on international keyboard */
+#define SCANCODE_KEY_42 0x2b
+
+#define SCANCODE_KEY_43 0x1c
+#define SCANCODE_CHAR_ENTER SCANCODE_KEY_43
+
+#define SCANCODE_KEY_44 0x2a
+#define SCANCODE_CHAR_LSHIFT SCANCODE_KEY_44
+
+/* Only on international keyboard */
+#define SCANCODE_KEY_45 0x56
+
+#define SCANCODE_KEY_46 0x2c
+#define SCANCODE_CHAR_Z SCANCODE_KEY_46
+
+#define SCANCODE_KEY_47 0x2d
+#define SCANCODE_CHAR_X SCANCODE_KEY_47
+
+#define SCANCODE_KEY_48 0x2e
+#define SCANCODE_CHAR_C SCANCODE_KEY_48
+
+#define SCANCODE_KEY_49 0x2f
+#define SCANCODE_CHAR_V SCANCODE_KEY_49
+
+#define SCANCODE_KEY_50 0x30
+#define SCANCODE_CHAR_B SCANCODE_KEY_50
+
+#define SCANCODE_KEY_51 0x31
+#define SCANCODE_CHAR_N SCANCODE_KEY_51
+
+#define SCANCODE_KEY_52 0x32
+#define SCANCODE_CHAR_M SCANCODE_KEY_52
+
+#define SCANCODE_KEY_53 0x33
+#define SCANCODE_CHAR_COMMA SCANCODE_KEY_53
+
+#define SCANCODE_KEY_54 0x34
+#define SCANCODE_CHAR_DOT SCANCODE_KEY_54
+
+#define SCANCODE_KEY_55 0x35
+#define SCANCODE_CHAR_SLASH SCANCODE_KEY_55
+
+/* Only on Brazilian and some Far East keyboards */
+#define SCANCODE_KEY_56 0x73
+
+#define SCANCODE_KEY_57 0x36
+#define SCANCODE_CHAR_RSHIFT SCANCODE_KEY_57
+
+#define SCANCODE_KEY_58 0x1d
+#define SCANCODE_CHAR_LCTRL SCANCODE_KEY_58
+
+/* Key 59 does not exist */
+
+#define SCANCODE_KEY_60 0x38
+#define SCANCODE_CHAR_LALT SCANCODE_KEY_60
+
+#define SCANCODE_KEY_61 0x39
+#define SCANCODE_CHAR_SPACE SCANCODE_KEY_61
+
+#define SCANCODE_KEY_62 (SCANCODE_EXTENDED | 0x38)
+#define SCANCODE_CHAR_RALT SCANCODE_KEY_62
+
+/* Key 63 does not exist */
+
+#define SCANCODE_KEY_64 (SCANCODE_EXTENDED | 0x1d)
+#define SCANCODE_CHAR_RCTRL SCANCODE_KEY_64
+
+/* Key 65 - 74 does not exist */
+
+#define SCANCODE_KEY_75 (SCANCODE_EXTENDED | 0x52)
+#define SCANCODE_CHAR_INSERT SCANCODE_KEY_75
+
+#define SCANCODE_KEY_76 (SCANCODE_EXTENDED | 0x53)
+#define SCANCODE_CHAR_DELETE SCANCODE_KEY_76
+
+/* Key 77 - 78 does not exist */
+
+#define SCANCODE_KEY_79 (SCANCODE_EXTENDED | 0x4b)
+#define SCANCODE_CHAR_LARROW SCANCODE_KEY_79
+
+#define SCANCODE_KEY_80 (SCANCODE_EXTENDED | 0x47)
+#define SCANCODE_CHAR_HOME SCANCODE_KEY_80
+
+#define SCANCODE_KEY_81 (SCANCODE_EXTENDED | 0x4f)
+#define SCANCODE_CHAR_END SCANCODE_KEY_81
+
+/* Key 82 does not exist */
+
+#define SCANCODE_KEY_83 (SCANCODE_EXTENDED | 0x48)
+#define SCANCODE_CHAR_UPARROW SCANCODE_KEY_83
+
+#define SCANCODE_KEY_84 (SCANCODE_EXTENDED | 0x50)
+#define SCANCODE_CHAR_DNARROW SCANCODE_KEY_84
+
+#define SCANCODE_KEY_85 (SCANCODE_EXTENDED | 0x49)
+#define SCANCODE_CHAR_PAGEUP SCANCODE_KEY_85
+
+#define SCANCODE_KEY_86 (SCANCODE_EXTENDED | 0x51)
+#define SCANCODE_CHAR_PAGEDOWN SCANCODE_KEY_86
+
+/* Key 87 - 88 does not exist */
+
+#define SCANCODE_KEY_89 (SCANCODE_EXTENDED | 0x4d)
+#define SCANCODE_CHAR_RARROW SCANCODE_KEY_89
+
+#define SCANCODE_KEY_90 0x45
+#define SCANCODE_CHAR_NUMLOCK SCANCODE_KEY_90
+
+#define SCANCODE_KEY_91 0x47
+#define SCANCODE_CHAR_NUMERIC7 SCANCODE_KEY_91
+
+#define SCANCODE_KEY_92 0x4b
+#define SCANCODE_CHAR_NUMERIC4 SCANCODE_KEY_92
+
+#define SCANCODE_KEY_93 0x4f
+#define SCANCODE_CHAR_NUMERIC1 SCANCODE_KEY_93
+
+/* Key 94 does not exist */
+
+#define SCANCODE_KEY_95 (SCANCODE_EXTENDED | 0x35)
+#define SCANCODE_CHAR_NUMERICSLASH SCANCODE_KEY_95
+
+#define SCANCODE_KEY_96 0x48
+#define SCANCODE_CHAR_NUMERIC8 SCANCODE_KEY_96
+
+#define SCANCODE_KEY_97 0x4c
+#define SCANCODE_CHAR_NUMERIC5 SCANCODE_KEY_97
+
+#define SCANCODE_KEY_98 0x50
+#define SCANCODE_CHAR_NUMERIC2 SCANCODE_KEY_98
+
+#define SCANCODE_KEY_99 0x52
+#define SCANCODE_CHAR_NUMERIC0 SCANCODE_KEY_99
+
+#define SCANCODE_KEY_100 0x37
+#define SCANCODE_CHAR_NUMERICSTAR SCANCODE_KEY_100
+
+#define SCANCODE_KEY_101 0x49
+#define SCANCODE_CHAR_NUMERIC9 SCANCODE_KEY_101
+
+#define SCANCODE_KEY_102 0x4d
+#define SCANCODE_CHAR_NUMERIC6 SCANCODE_KEY_102
+
+#define SCANCODE_KEY_103 0x51
+#define SCANCODE_CHAR_NUMERIC3 SCANCODE_KEY_103
+
+#define SCANCODE_KEY_104 0x53
+#define SCANCODE_CHAR_NUMERICDOT SCANCODE_KEY_104
+
+#define SCANCODE_KEY_105 0x4a
+#define SCANCODE_CHAR_NUMERICMINUS SCANCODE_KEY_105
+
+#define SCANCODE_KEY_106 0x4e
+#define SCANCODE_CHAR_NUMERICPLUS SCANCODE_KEY_106
+
+/* Only on Brazilian and some Far East keyboards */
+#define SCANCODE_KEY_107 0x
+
+#define SCANCODE_KEY_108 (SCANCODE_EXTENDED | 0x1c)
+#define SCANCODE_CHAR_NUMERICENTER SCANCODE_KEY_108
+
+/* Key 109 does not exist */
+
+#define SCANCODE_KEY_110 0x1
+#define SCANCODE_CHAR_ESC SCANCODE_KEY_110
+
+/* Key 111 does not exist */
+
+#define SCANCODE_KEY_112 0x3b
+#define SCANCODE_CHAR_F1 SCANCODE_KEY_112
+
+#define SCANCODE_KEY_113 0x3c
+#define SCANCODE_CHAR_F2 SCANCODE_KEY_113
+
+#define SCANCODE_KEY_114 0x3d
+#define SCANCODE_CHAR_F3 SCANCODE_KEY_114
+
+#define SCANCODE_KEY_115 0x3e
+#define SCANCODE_CHAR_F4 SCANCODE_KEY_115
+
+#define SCANCODE_KEY_116 0x3f
+#define SCANCODE_CHAR_F5 SCANCODE_KEY_116
+
+#define SCANCODE_KEY_117 0x40
+#define SCANCODE_CHAR_F6 SCANCODE_KEY_117
+
+#define SCANCODE_KEY_118 0x41
+#define SCANCODE_CHAR_F7 SCANCODE_KEY_118
+
+#define SCANCODE_KEY_119 0x42
+#define SCANCODE_CHAR_F8 SCANCODE_KEY_119
+
+#define SCANCODE_KEY_120 0x43
+#define SCANCODE_CHAR_F9 SCANCODE_KEY_120
+
+#define SCANCODE_KEY_121 0x44
+#define SCANCODE_CHAR_F10 SCANCODE_KEY_121
+
+#define SCANCODE_KEY_122 0x57
+#define SCANCODE_CHAR_F11 SCANCODE_KEY_122
+
+#define SCANCODE_KEY_123 0x58
+#define SCANCODE_CHAR_F12 SCANCODE_KEY_123
+
+/* Key 124: The Print Screen sequence is complicated, and
+   hardcoded in xkeymap.c */
+
+#define SCANCODE_KEY_125 0x46
+#define SCANCODE_CHAR_SCROLLLOCK SCANCODE_KEY_125
+
+/* Key 126: The Pause and Break sequences is complicated, and
+   hardcoded in xkeymap.c */
+
+/* 
+   The keys below does not have any key location number
+*/
+
+#define SCANCODE_CHAR_LWIN (SCANCODE_EXTENDED | 0x5b)
+
+#define SCANCODE_CHAR_RWIN (SCANCODE_EXTENDED | 0x5c)
+
+#define SCANCODE_CHAR_APPLICATION (SCANCODE_EXTENDED | 0x5d)
+
+#define SCANCODE_CHAR_ACPIPOWER (SCANCODE_EXTENDED | 0x5e)
+
+#define SCANCODE_CHAR_ACPISLEEP (SCANCODE_EXTENDED | 0x5f)
+
+#define SCANCODE_CHAR_ACPIWAKE (SCANCODE_EXTENDED | 0x63)
Index: /trunk/src/VBox/RDP/client-1.8.3/scard.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/scard.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/scard.c	(revision 55121)
@@ -0,0 +1,2692 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   Smart Card support
+   Copyright (C) Alexi Volkov <alexi@myrealbox.com> 2006
+   Copyright 2010-2013 Pierre Ossman <ossman@cendio.se> for Cendio AB
+   Copyright 2011-2014 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <time.h>
+#include <arpa/inet.h>
+#ifndef MAKE_PROTO
+#ifdef __APPLE__
+#include <PCSC/wintypes.h>
+#include <PCSC/pcsclite.h>
+#include <PCSC/winscard.h>
+#else
+#include <wintypes.h>
+#include <pcsclite.h>
+#include <winscard.h>
+#ifdef PCSCLITE_VERSION_NUMBER
+#include <reader.h>
+#endif
+#endif /* PCSC_OSX */
+#include "rdesktop.h"
+#include "scard.h"
+
+/* variable segment */
+
+#define SCARD_MAX_MEM 102400
+#ifndef SCARD_AUTOALLOCATE
+#define SCARD_AUTOALLOCATE -1
+#endif
+#define	OUT_STREAM_SIZE	4096
+
+#ifdef B_ENDIAN
+#define swap32(x)	((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) |	\
+			(((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24))
+
+#define	swap16(x)	((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
+#else
+#define	swap32(x)	(x)
+#define	swap16(x)	(x)
+#endif
+
+static pthread_mutex_t **scard_mutex = NULL;
+
+static uint32 curEpoch = 0, curDevice = 0, curId = 0, curBytesOut = 0;
+static PSCNameMapRec nameMapList = NULL;
+static int nameMapCount = 0;
+
+static pthread_t queueHandler;
+static pthread_mutex_t queueAccess;
+static pthread_cond_t queueEmpty;
+static pthread_mutex_t hcardAccess;
+
+static PMEM_HANDLE threadListHandle = NULL;
+static PThreadListElement threadList = NULL;
+
+
+static PSCThreadData queueFirst = NULL, queueLast = NULL;
+static int threadCount = 0;
+
+static PSCHCardRec hcardFirst = NULL;
+
+static void *queue_handler_function(void *data);
+
+/* code segment */
+
+#endif /* MAKE_PROTO */
+void
+scardSetInfo(uint32 epoch, uint32 device, uint32 id, uint32 bytes_out)
+{
+	curDevice = device;
+	curId = id;
+	curBytesOut = bytes_out;
+	curEpoch = epoch;
+}
+
+#ifndef MAKE_PROTO
+
+static RD_NTSTATUS
+scard_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
+	     uint32 flags_and_attributes, char *filename, RD_NTHANDLE * phandle)
+{
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+scard_close(RD_NTHANDLE handle)
+{
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+scard_read(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
+{
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+scard_write(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
+{
+	return RD_STATUS_SUCCESS;
+}
+#endif /* MAKE_PROTO */
+
+/* Enumeration of devices from rdesktop.c        */
+/* returns numer of units found and initialized. */
+/* optarg looks like ':"ReaderName=ReaderAlias"' */
+/* when it arrives to this function.             */
+
+int
+scard_enum_devices(uint32 * id, char *optarg)
+{
+	char *name = optarg + 1;
+	char *alias;
+	int count = 0;
+	PSCNameMapRec tmpMap;
+
+	MYPCSC_DWORD rv;
+	SCARDCONTEXT hContext;
+
+	/* code segment  */
+	rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
+	if (rv != SCARD_S_SUCCESS)
+	{
+		error("scard_enum_devices: PCSC service not available\n");
+		return 0;
+	}
+	else
+		rv = SCardReleaseContext(hContext);
+
+	count = 0;
+
+	if (0 != pthread_mutex_init(&queueAccess, NULL))
+	{
+		error("scard_enum_devices: Can't initialize queue access mutex\n");
+		return 0;
+	}
+
+	if (0 != pthread_cond_init(&queueEmpty, NULL))
+	{
+		error("scard_enum_devices: Can't initialize queue control cv\n");
+		return 0;
+	}
+
+	if (0 != pthread_mutex_init(&hcardAccess, NULL))
+	{
+		error("scard_enum_devices: Can't initialize hcard list access mutex\n");
+		return 0;
+	}
+
+	if (0 !=
+	    pthread_create(&queueHandler, NULL, (void *(*)(void *)) queue_handler_function, NULL))
+	{
+		error("scard_enum_devices: Can't create queue handling Thread\n");
+		return 0;
+	}
+
+	strncpy(g_rdpdr_device[*id].name, "SCARD\0\0\0", 8);
+	toupper_str(g_rdpdr_device[*id].name);
+	g_rdpdr_device[*id].local_path = "/dev/scard";
+	g_rdpdr_device[*id].pdevice_data = NULL;
+	g_rdpdr_device[*id].handle = 0;
+	g_rdpdr_device[*id].device_type = DEVICE_TYPE_SCARD;
+	count++;
+	(*id)++;
+
+	if (*optarg == ':')
+	{
+		while ((optarg = next_arg(name, ',')) && *id < RDPDR_MAX_DEVICES)
+		{
+			int len;
+			char *vendor = NULL;
+			alias = next_arg(name, '=');
+			vendor = next_arg(alias, ';');
+
+			if (strlen(name) > 0)
+			{
+				if (!strlen(alias))
+				{
+					alias = name;
+					vendor = "\0";
+				}
+
+				printf("Static/aliased Device:\n");
+				printf("  Lin name: [%s]\n", name);
+				printf("  Win name: [%s]\n", alias);
+				printf("  Vendor  : [%s]\n", vendor);
+				nameMapCount++;
+
+				if (nameMapList == NULL)
+					nameMapList = xmalloc(nameMapCount * sizeof(TSCNameMapRec));
+				else
+					nameMapList =
+						xrealloc(nameMapList,
+							 nameMapCount * sizeof(TSCNameMapRec));
+
+				tmpMap = nameMapList + nameMapCount - 1;
+
+				len = strlen(alias);
+				strncpy(tmpMap->alias, alias, (len > 127) ? (127) : (len));
+				len = strlen(name);
+				strncpy(tmpMap->name, name, (len > 127) ? (127) : (len));
+
+				if (vendor)
+				{
+					len = strlen(vendor);
+					if (len > 0)
+					{
+						memset(tmpMap->vendor, 0, 128);
+						strncpy(tmpMap->vendor, vendor,
+							(len > 127) ? (127) : (len));
+					}
+					else
+						tmpMap->vendor[0] = '\0';
+				}
+				else
+					tmpMap->vendor[0] = '\0';
+			}
+			name = optarg;
+		}
+	}
+
+	return count;
+}
+
+#ifndef MAKE_PROTO
+typedef struct _scard_handle_list_t
+{
+	struct _scard_handle_list_t *next;
+	/* pcsc handles is datatype long which 
+	   is arch sizedependent */
+	long handle;
+	/* rdp server handles are always 32bit */
+	uint32_t server;
+} _scard_handle_list_t;
+
+static uint32_t g_scard_handle_counter = 0;
+static _scard_handle_list_t *g_scard_handle_list = NULL;
+
+static void _scard_handle_list_add(long handle);
+static void _scard_handle_list_remove(long handle);
+static uint32_t _scard_handle_list_get_server_handle(long handle);
+static long _scard_handle_list_get_pcsc_handle(uint32_t server);
+
+void
+_scard_handle_list_add(long handle)
+{
+	_scard_handle_list_t *list = g_scard_handle_list;
+	/* we dont care of order of list so to simplify the add 
+	   we add new items to front of list */
+	_scard_handle_list_t *item = xmalloc(sizeof(_scard_handle_list_t));
+	item->next = list;
+	item->handle = handle;
+
+	/* lookup first unused handle id */
+	int overlap = 0;
+	if (g_scard_handle_counter == 0)
+		g_scard_handle_counter++;
+
+	while (_scard_handle_list_get_pcsc_handle(g_scard_handle_counter))
+	{
+		g_scard_handle_counter++;
+
+		if (g_scard_handle_counter == 0 && overlap)
+			assert(!"broken smartcard client software, handles are not freed and there is no more handles left to allocate.");
+
+		if (g_scard_handle_counter == 0)
+			overlap = g_scard_handle_counter = 1;
+
+	}
+
+	item->server = g_scard_handle_counter;
+	g_scard_handle_list = item;
+}
+
+void
+_scard_handle_list_remove(long handle)
+{
+	_scard_handle_list_t *item, *list, *prev_item;
+	prev_item = NULL;
+	item = list = g_scard_handle_list;
+
+	while (item)
+	{
+		if (item->handle == handle)
+		{
+			/* unlink from list */
+			if (prev_item)
+				prev_item->next = item->next;
+			else
+				g_scard_handle_list = item->next;
+
+			xfree(item);
+			break;
+		}
+
+		/* store previous item for relinking */
+		prev_item = item;
+		item = item->next;
+	}
+}
+
+uint32_t
+_scard_handle_list_get_server_handle(long handle)
+{
+	_scard_handle_list_t *item;
+	item = g_scard_handle_list;
+	while (item)
+	{
+		if (item->handle == handle)
+			return item->server;
+		item = item->next;
+	}
+	return 0;
+}
+
+long
+_scard_handle_list_get_pcsc_handle(uint32_t server)
+{
+	_scard_handle_list_t *item;
+	item = g_scard_handle_list;
+	while (item)
+	{
+		if (item->server == server)
+			return item->handle;
+		item = item->next;
+	}
+	return 0;
+}
+
+static void *
+SC_xmalloc(PMEM_HANDLE * memHandle, unsigned int size)
+{
+	PMEM_HANDLE handle = NULL;
+	if (size > 0 && memHandle)
+	{
+		handle = xmalloc(size + sizeof(MEM_HANDLE));
+		if (handle)
+		{
+			handle->prevHandle = NULL;
+			handle->nextHandle = NULL;
+			handle->dataSize = size;
+			if (*memHandle)
+			{
+				handle->prevHandle = *memHandle;
+				(*memHandle)->nextHandle = handle;
+			}
+			*memHandle = handle;
+			return handle + 1;
+		}
+		else
+			return NULL;
+	}
+	else
+		return NULL;
+}
+
+static void
+SC_xfree(PMEM_HANDLE * handle, void *memptr)
+{
+	if (memptr != NULL)
+	{
+		PMEM_HANDLE lcHandle = (PMEM_HANDLE) memptr - 1;
+		if (lcHandle->dataSize > 0)
+		{
+			memset(memptr, 0, lcHandle->dataSize);
+			if (lcHandle->nextHandle)
+				lcHandle->nextHandle->prevHandle = lcHandle->prevHandle;
+			if (lcHandle->prevHandle)
+				lcHandle->prevHandle->nextHandle = lcHandle->nextHandle;
+			if (*handle == lcHandle)
+			{
+				if (lcHandle->prevHandle)
+					*handle = lcHandle->prevHandle;
+				else
+					*handle = lcHandle->nextHandle;
+			}
+			xfree(lcHandle);
+		}
+	}
+}
+
+static void
+SC_xfreeallmemory(PMEM_HANDLE * handle)
+{
+	if (handle && (*handle))
+	{
+		if ((*handle)->prevHandle)
+		{
+			(*handle)->prevHandle->nextHandle = NULL;
+			SC_xfreeallmemory(&((*handle)->prevHandle));
+		}
+		if ((*handle)->nextHandle)
+		{
+			(*handle)->nextHandle->prevHandle = NULL;
+			SC_xfreeallmemory(&((*handle)->nextHandle));
+		}
+		memset(*handle, 0, (*handle)->dataSize + sizeof(MEM_HANDLE));
+		xfree(*handle);
+		*handle = NULL;
+	}
+}
+
+/* ---------------------------------- */
+
+static char *
+getName(char *alias)
+{
+	int i;
+	PSCNameMapRec tmpMap;
+	for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
+	{
+		if (strcmp(tmpMap->alias, alias) == 0)
+			return tmpMap->name;
+	}
+	return alias;
+}
+
+static char *
+getVendor(char *name)
+{
+	int i;
+	PSCNameMapRec tmpMap;
+	for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
+	{
+		if (strcmp(tmpMap->name, name) == 0)
+			return tmpMap->vendor;
+	}
+	return NULL;
+}
+
+
+static char *
+getAlias(char *name)
+{
+	int i;
+	PSCNameMapRec tmpMap;
+	for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
+	{
+		if (strcmp(tmpMap->name, name) == 0)
+			return tmpMap->alias;
+	}
+	return name;
+}
+
+static int
+hasAlias(char *name)
+{
+	int i;
+	PSCNameMapRec tmpMap;
+	for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
+	{
+		if (strcmp(tmpMap->name, name) == 0)
+			return 1;
+	}
+	return 0;
+}
+
+static void
+inRepos(STREAM in, unsigned int read)
+{
+	SERVER_DWORD add = 4 - read % 4;
+	if (add < 4 && add > 0)
+	{
+		in_uint8s(in, add);
+	}
+}
+
+static void
+outRepos(STREAM out, unsigned int written)
+{
+	SERVER_DWORD add = (4 - written % 4) % 4;
+	if (add > 0)
+	{
+		out_uint8s(out, add);
+	}
+}
+
+
+static void
+outBufferStartWithLimit(STREAM out, int length, int highLimit)
+{
+	int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
+	out_uint32_le(out, header);
+	out_uint32_le(out, 0x00000001);	/* Magic DWORD - any non zero */
+}
+
+
+static void
+outBufferStart(STREAM out, int length)
+{
+	outBufferStartWithLimit(out, length, 0x7FFFFFFF);
+}
+
+static void
+outBufferFinishWithLimit(STREAM out, char *buffer, unsigned int length, unsigned int highLimit)
+{
+	int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
+	out_uint32_le(out, header);
+
+	if (length <= 0)
+	{
+		out_uint32_le(out, 0x00000000);
+	}
+	else
+	{
+		if (header < length)
+			length = header;
+		out_uint8p(out, buffer, length);
+		outRepos(out, length);
+	}
+}
+
+static void
+outBufferFinish(STREAM out, char *buffer, unsigned int length)
+{
+	outBufferFinishWithLimit(out, buffer, length, 0x7FFFFFFF);
+}
+
+static void
+outForceAlignment(STREAM out, unsigned int seed)
+{
+	SERVER_DWORD add = (seed - (out->p - out->data) % seed) % seed;
+	if (add > 0)
+		out_uint8s(out, add);
+}
+
+static unsigned int
+inString(PMEM_HANDLE * handle, STREAM in, char **destination, SERVER_DWORD dataLength, RD_BOOL wide)
+{
+	unsigned int Result = (wide) ? (2 * dataLength) : (dataLength);
+	PMEM_HANDLE lcHandle = NULL;
+	char *buffer = SC_xmalloc(&lcHandle, Result + 2);
+	char *reader;
+
+	/* code segment */
+
+	if (wide)
+	{
+		int i;
+		in_uint8a(in, buffer, 2 * dataLength);
+		for (i = 0; i < dataLength; i++)
+			if ((buffer[2 * i] < 0) || (buffer[2 * i + 1] != 0))
+				buffer[i] = '?';
+			else
+				buffer[i] = buffer[2 * i];
+	}
+	else
+	{
+		in_uint8a(in, buffer, dataLength);
+	}
+
+	buffer[dataLength] = '\0';
+	reader = getName(buffer);
+	*destination = SC_xmalloc(handle, strlen(reader) + 1);
+	strcpy(*destination, reader);
+
+	SC_xfreeallmemory(&lcHandle);
+	return Result;
+}
+
+static unsigned int
+outString(STREAM out, char *source, RD_BOOL wide)
+{
+	PMEM_HANDLE lcHandle = NULL;
+	char *reader = getAlias(source);
+	unsigned int dataLength = strlen(reader) + 1;
+	unsigned int Result = (wide) ? (2 * dataLength) : (dataLength);
+
+	/* code segment */
+
+	if (wide)
+	{
+		int i;
+		char *buffer = SC_xmalloc(&lcHandle, Result);
+
+		for (i = 0; i < dataLength; i++)
+		{
+			if (source[i] < 0)
+				buffer[2 * i] = '?';
+			else
+				buffer[2 * i] = reader[i];
+			buffer[2 * i + 1] = '\0';
+		}
+		out_uint8p(out, buffer, 2 * dataLength);
+	}
+	else
+	{
+		out_uint8p(out, reader, dataLength);
+	}
+
+	SC_xfreeallmemory(&lcHandle);
+	return Result;
+}
+
+static void
+inReaderName(PMEM_HANDLE * handle, STREAM in, char **destination, RD_BOOL wide)
+{
+	SERVER_DWORD dataLength;
+	in->p += 0x08;
+	in_uint32_le(in, dataLength);
+	inRepos(in, inString(handle, in, destination, dataLength, wide));
+}
+
+static void
+inSkipLinked(STREAM in)
+{
+	SERVER_DWORD len;
+	in_uint32_le(in, len);
+	if (len > 0)
+	{
+		in_uint8s(in, len);
+		inRepos(in, len);
+	}
+}
+
+/* ---------------------------------- */
+/*  Smart Card processing functions:  */
+/* ---------------------------------- */
+
+static MYPCSC_DWORD
+SC_returnCode(MYPCSC_DWORD rc, PMEM_HANDLE * handle, STREAM in, STREAM out)
+{
+	SC_xfreeallmemory(handle);
+	out_uint8s(out, 256);
+	return rc;
+}
+
+static MYPCSC_DWORD
+SC_returnNoMemoryError(PMEM_HANDLE * handle, STREAM in, STREAM out)
+{
+	return SC_returnCode(SCARD_E_NO_MEMORY, handle, in, out);
+}
+
+static MYPCSC_DWORD
+TS_SCardEstablishContext(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	MYPCSC_SCARDCONTEXT myHContext;
+	SERVER_SCARDCONTEXT hContext;
+
+	/* code segment  */
+
+	DEBUG_SCARD(("SCARD: SCardEstablishContext()\n"));
+	rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &myHContext);
+
+	hContext = 0;
+	if (myHContext)
+	{
+		_scard_handle_list_add(myHContext);
+		hContext = _scard_handle_list_get_server_handle(myHContext);
+	}
+
+
+	if (rv)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success (context: 0x%08x [0x%lx])\n", hContext,
+			     myHContext));
+	}
+
+
+
+	out_uint32_le(out, 0x00000004);
+	out_uint32_le(out, hContext);	/* must not be 0 (Seems to be pointer), don't know what is this (I use hContext as value) */
+	/* i hope it's not a pointer because i just downcasted it - jlj */
+	out_uint32_le(out, 0x00000004);
+	out_uint32_le(out, hContext);
+	outForceAlignment(out, 8);
+	return rv;
+}
+
+static MYPCSC_DWORD
+TS_SCardReleaseContext(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	MYPCSC_SCARDCONTEXT myHContext;
+	SERVER_SCARDCONTEXT hContext;
+
+	in->p += 0x1C;
+	in_uint32_le(in, hContext);
+	myHContext = _scard_handle_list_get_pcsc_handle(hContext);
+
+	DEBUG_SCARD(("SCARD: SCardReleaseContext(context: 0x%08x [0x%lx])\n", (unsigned) hContext,
+		     myHContext));
+
+	rv = SCardReleaseContext(myHContext);
+
+	_scard_handle_list_remove(myHContext);
+
+	if (rv)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success\n"));
+	}
+
+	outForceAlignment(out, 8);
+	return rv;
+}
+
+static MYPCSC_DWORD
+TS_SCardIsValidContext(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hContext;
+	MYPCSC_SCARDCONTEXT myHContext;
+	char *readers;
+	DWORD readerCount = 1024;
+	PMEM_HANDLE lcHandle = NULL;
+
+	in->p += 0x1C;
+	in_uint32_le(in, hContext);
+
+	myHContext = _scard_handle_list_get_pcsc_handle(hContext);
+
+	DEBUG_SCARD(("SCARD: SCardIsValidContext(context: 0x%08x [0x%lx])\n",
+		     (unsigned) hContext, myHContext));
+	/* There is no realization of SCardIsValidContext in PC/SC Lite so we call SCardListReaders */
+
+	readers = SC_xmalloc(&lcHandle, 1024);
+	if (!readers)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+
+	rv = SCardListReaders(myHContext, NULL, readers, &readerCount);
+
+	if (rv)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+		rv = SCARD_E_INVALID_HANDLE;
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success\n"));
+	}
+
+	outForceAlignment(out, 8);
+	SC_xfreeallmemory(&lcHandle);
+	return rv;
+}
+
+
+static MYPCSC_DWORD
+TS_SCardListReaders(STREAM in, STREAM out, RD_BOOL wide)
+{
+#define readerArraySize 1024
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hContext;
+	MYPCSC_SCARDCONTEXT myHContext;
+	SERVER_DWORD dataLength;
+	MYPCSC_DWORD cchReaders = readerArraySize;
+	unsigned char *plen1, *plen2, *pend;
+	char *readers, *cur;
+	PMEM_HANDLE lcHandle = NULL;
+
+	in->p += 0x2C;
+	in_uint32_le(in, hContext);
+	myHContext = _scard_handle_list_get_pcsc_handle(hContext);
+	DEBUG_SCARD(("SCARD: SCardListReaders(context: 0x%08x [0x%lx])\n",
+		     (unsigned) hContext, myHContext));
+	plen1 = out->p;
+	out_uint32_le(out, 0x00000000);	/* Temp value for data length as 0x0 */
+	out_uint32_le(out, 0x01760650);
+	plen2 = out->p;
+	out_uint32_le(out, 0x00000000);	/* Temp value for data length as 0x0 */
+
+	dataLength = 0;
+	readers = SC_xmalloc(&lcHandle, readerArraySize);
+	if (!readers)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+
+
+	readers[0] = '\0';
+	readers[1] = '\0';
+	rv = SCardListReaders(myHContext, NULL, readers, &cchReaders);
+	cur = readers;
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		int i;
+		PSCNameMapRec tmpMap;
+		DEBUG_SCARD(("SCARD: -> Success\n"));
+		for (i = 0, tmpMap = nameMapList; i < nameMapCount; i++, tmpMap++)
+		{
+			dataLength += outString(out, tmpMap->alias, wide);
+		}
+
+		int lenSC = strlen(cur);
+		if (lenSC == 0)
+			dataLength += outString(out, "\0", wide);
+		else
+			while (lenSC > 0)
+			{
+				if (!hasAlias(cur))
+				{
+					DEBUG_SCARD(("SCARD:    \"%s\"\n", cur));
+					dataLength += outString(out, cur, wide);
+				}
+				cur = (void *) ((unsigned char *) cur + lenSC + 1);
+				lenSC = strlen(cur);
+			}
+	}
+
+	dataLength += outString(out, "\0", wide);
+	outRepos(out, dataLength);
+
+	pend = out->p;
+	out->p = plen1;
+	out_uint32_le(out, dataLength);
+	out->p = plen2;
+	out_uint32_le(out, dataLength);
+	out->p = pend;
+
+	outForceAlignment(out, 8);
+	SC_xfreeallmemory(&lcHandle);
+	return rv;
+}
+
+
+static MYPCSC_DWORD
+TS_SCardConnect(STREAM in, STREAM out, RD_BOOL wide)
+{
+	MYPCSC_DWORD rv;
+	SCARDCONTEXT myHContext;
+	SERVER_SCARDCONTEXT hContext;
+	char *szReader;
+	SERVER_DWORD dwShareMode;
+	SERVER_DWORD dwPreferredProtocol;
+	MYPCSC_SCARDHANDLE myHCard;
+	SERVER_SCARDHANDLE hCard;
+
+	MYPCSC_DWORD dwActiveProtocol;
+	PMEM_HANDLE lcHandle = NULL;
+
+	in->p += 0x1C;
+	in_uint32_le(in, dwShareMode);
+	in_uint32_le(in, dwPreferredProtocol);
+	inReaderName(&lcHandle, in, &szReader, wide);
+	in->p += 0x04;
+	in_uint32_le(in, hContext);
+
+	myHContext = _scard_handle_list_get_pcsc_handle(hContext);
+
+	DEBUG_SCARD(("SCARD: SCardConnect(context: 0x%08x [0x%lx], share: 0x%08x, proto: 0x%08x, reader: \"%s\")\n", (unsigned) hContext, myHContext, (unsigned) dwShareMode, (unsigned) dwPreferredProtocol, szReader ? szReader : "NULL"));
+
+	rv = SCardConnect(myHContext, szReader, (MYPCSC_DWORD) dwShareMode,
+			  (MYPCSC_DWORD) dwPreferredProtocol, &myHCard, &dwActiveProtocol);
+
+	hCard = 0;
+	if (myHCard)
+	{
+		_scard_handle_list_add(myHCard);
+		hCard = _scard_handle_list_get_server_handle(myHCard);
+	}
+
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		char *szVendor = getVendor(szReader);
+		DEBUG_SCARD(("SCARD: -> Success (hcard: 0x%08x [0x%lx])\n",
+			     (unsigned) hCard, myHCard));
+		if (szVendor && (strlen(szVendor) > 0))
+		{
+			DEBUG_SCARD(("SCARD: Set Attribute ATTR_VENDOR_NAME\n"));
+			pthread_mutex_lock(&hcardAccess);
+			PSCHCardRec hcard = xmalloc(sizeof(TSCHCardRec));
+			if (hcard)
+			{
+				hcard->hCard = hCard;
+				hcard->vendor = szVendor;
+				hcard->next = NULL;
+				hcard->prev = NULL;
+
+				if (hcardFirst)
+				{
+					hcardFirst->prev = hcard;
+					hcard->next = hcardFirst;
+				}
+				hcardFirst = hcard;
+			}
+			pthread_mutex_unlock(&hcardAccess);
+		}
+	}
+
+	out_uint32_le(out, 0x00000000);
+	out_uint32_le(out, 0x00000000);
+	out_uint32_le(out, 0x00000004);
+	out_uint32_le(out, 0x016Cff34);
+	/* if the active protocol > 4 billion, this is trouble. odds are low */
+	out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
+	out_uint32_le(out, 0x00000004);
+	out_uint32_le(out, hCard);
+
+	outForceAlignment(out, 8);
+	SC_xfreeallmemory(&lcHandle);
+	return rv;
+}
+
+static MYPCSC_DWORD
+TS_SCardReconnect(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hContext;
+	SERVER_SCARDHANDLE hCard;
+	MYPCSC_SCARDHANDLE myHCard;
+	SERVER_DWORD dwShareMode;
+	SERVER_DWORD dwPreferredProtocol;
+	SERVER_DWORD dwInitialization;
+	MYPCSC_DWORD dwActiveProtocol;
+
+	in->p += 0x20;
+	in_uint32_le(in, dwShareMode);
+	in_uint32_le(in, dwPreferredProtocol);
+	in_uint32_le(in, dwInitialization);
+	in->p += 0x04;
+	in_uint32_le(in, hContext);
+	in->p += 0x04;
+	in_uint32_le(in, hCard);
+
+
+	myHCard = _scard_handle_list_get_pcsc_handle(hCard);
+	DEBUG_SCARD(("SCARD: SCardReconnect(context: 0x%08x, hcard: 0x%08x [%lx], share: 0x%08x, proto: 0x%08x, init: 0x%08x)\n", (unsigned) hContext, (unsigned) hCard, myHCard, (unsigned) dwShareMode, (unsigned) dwPreferredProtocol, (unsigned) dwInitialization));
+	rv = SCardReconnect(myHCard, (MYPCSC_DWORD) dwShareMode, (MYPCSC_DWORD) dwPreferredProtocol,
+			    (MYPCSC_DWORD) dwInitialization, &dwActiveProtocol);
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success (proto: 0x%08x)\n", (unsigned) dwActiveProtocol));
+	}
+
+	out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
+	outForceAlignment(out, 8);
+	return rv;
+}
+
+static MYPCSC_DWORD
+TS_SCardDisconnect(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hContext;
+	MYPCSC_SCARDCONTEXT myHContext;
+	SERVER_SCARDHANDLE hCard;
+	MYPCSC_SCARDHANDLE myHCard;
+	SERVER_DWORD dwDisposition;
+
+	in->p += 0x20;
+	in_uint32_le(in, dwDisposition);
+	in->p += 0x04;
+	in_uint32_le(in, hContext);
+	in->p += 0x04;
+	in_uint32_le(in, hCard);
+
+	myHContext = _scard_handle_list_get_pcsc_handle(hContext);
+	myHCard = _scard_handle_list_get_pcsc_handle(hCard);
+
+	DEBUG_SCARD(("SCARD: SCardDisconnect(context: 0x%08x [0x%lx], hcard: 0x%08x [0x%lx], disposition: 0x%08x)\n", (unsigned) hContext, myHContext, (unsigned) hCard, myHCard, (unsigned) dwDisposition));
+
+	pthread_mutex_lock(&hcardAccess);
+	PSCHCardRec hcard = hcardFirst;
+	while (hcard)
+	{
+		if (hcard->hCard == hCard)
+		{
+			if (hcard->prev)
+				hcard->prev->next = hcard->next;
+			if (hcard->next)
+				hcard->next->prev = hcard->prev;
+			if (hcardFirst == hcard)
+				hcardFirst = hcard->next;
+			xfree(hcard);
+			break;
+		}
+		hcard = hcard->next;
+	}
+	pthread_mutex_unlock(&hcardAccess);
+
+	rv = SCardDisconnect(myHCard, (MYPCSC_DWORD) dwDisposition);
+
+	_scard_handle_list_remove(myHCard);
+
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success\n"));
+	}
+
+	outForceAlignment(out, 8);
+	return rv;
+}
+
+/* Currently unused */
+#if 0
+static int
+needStatusRecheck(MYPCSC_DWORD rv, MYPCSC_LPSCARD_READERSTATE_A rsArray, SERVER_DWORD dwCount)
+{
+	int i, recall = 0;
+	if (rv == SCARD_S_SUCCESS)
+	{
+		MYPCSC_LPSCARD_READERSTATE_A cur;
+		for (i = 0, cur = rsArray; i < dwCount; i++, cur++)
+		{
+			if (cur->dwEventState & SCARD_STATE_UNKNOWN)
+			{
+				cur->dwCurrentState = cur->dwEventState;
+				recall++;
+			}
+		}
+	}
+	return recall;
+}
+
+static RD_BOOL
+mappedStatus(MYPCSC_DWORD code)
+{
+	code >>= 16;
+	code &= 0x0000FFFF;
+	return (code % 2);
+}
+#endif
+
+static void
+copyReaderState_MyPCSCToServer(MYPCSC_LPSCARD_READERSTATE_A src, SERVER_LPSCARD_READERSTATE_A dst,
+			       MYPCSC_DWORD readerCount)
+{
+	MYPCSC_LPSCARD_READERSTATE_A srcIter;
+	SERVER_LPSCARD_READERSTATE_A dstIter;
+	MYPCSC_DWORD i;
+
+	for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
+	{
+		dstIter->szReader = srcIter->szReader;
+		dstIter->pvUserData = srcIter->pvUserData;
+		dstIter->dwCurrentState = srcIter->dwCurrentState;
+		dstIter->dwEventState = srcIter->dwEventState;
+		dstIter->cbAtr = srcIter->cbAtr;
+		memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
+	}
+}
+
+static void
+copyReaderState_ServerToMyPCSC(SERVER_LPSCARD_READERSTATE_A src, MYPCSC_LPSCARD_READERSTATE_A dst,
+			       SERVER_DWORD readerCount)
+{
+	SERVER_LPSCARD_READERSTATE_A srcIter;
+	MYPCSC_LPSCARD_READERSTATE_A dstIter;
+	SERVER_DWORD i;
+
+	for (i = 0, srcIter = src, dstIter = dst; i < readerCount; i++, srcIter++, dstIter++)
+	{
+		dstIter->szReader = srcIter->szReader;
+		dstIter->pvUserData = srcIter->pvUserData;
+		dstIter->dwCurrentState = srcIter->dwCurrentState;
+		dstIter->dwEventState = srcIter->dwEventState;
+		dstIter->cbAtr = srcIter->cbAtr;
+		memcpy(dstIter->rgbAtr, srcIter->rgbAtr, MAX_ATR_SIZE * sizeof(unsigned char));
+	}
+}
+
+
+static MYPCSC_DWORD
+TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hContext;
+	MYPCSC_SCARDCONTEXT myHContext;
+	SERVER_DWORD dwTimeout;
+	SERVER_DWORD dwCount;
+	SERVER_DWORD dwPointerId;
+	SERVER_LPSCARD_READERSTATE_A rsArray, cur;
+	MYPCSC_LPSCARD_READERSTATE_A myRsArray;
+	long i;
+	PMEM_HANDLE lcHandle = NULL;
+
+	in->p += 0x18;
+	in_uint32_le(in, dwTimeout);
+	in_uint32_le(in, dwCount);
+	in->p += 0x08;
+	in_uint32_le(in, hContext);
+	in->p += 0x04;
+
+	myHContext = _scard_handle_list_get_pcsc_handle(hContext);
+
+	DEBUG_SCARD(("SCARD: SCardGetStatusChange(context: 0x%08x [0x%lx], timeout: 0x%08x, count: %d)\n", (unsigned) hContext, myHContext, (unsigned) dwTimeout, (int) dwCount));
+
+	if (dwCount > 0)
+	{
+		rsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
+		if (!rsArray)
+			return SC_returnNoMemoryError(&lcHandle, in, out);
+		memset(rsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
+		for (i = 0, cur = rsArray; i < dwCount; i++, cur++)
+		{
+			in_uint32_le(in, dwPointerId);
+			cur->szReader = (char *) (intptr_t) dwPointerId;
+			in_uint32_le(in, cur->dwCurrentState);
+			in_uint32_le(in, cur->dwEventState);
+			in_uint32_le(in, cur->cbAtr);
+			in_uint8a(in, cur->rgbAtr, sizeof(cur->rgbAtr));
+		}
+
+		for (i = 0, cur = rsArray; i < dwCount; i++, cur++)
+		{
+			if (cur->szReader != NULL)
+			{
+				SERVER_DWORD dataLength;
+
+				in->p += 0x08;
+				in_uint32_le(in, dataLength);
+				inRepos(in,
+					inString(&lcHandle, in, (char **) &(cur->szReader),
+						 dataLength, wide));
+
+				if (strcmp(cur->szReader, "\\\\?PnP?\\Notification") == 0)
+					cur->dwCurrentState |= SCARD_STATE_IGNORE;
+			}
+
+			DEBUG_SCARD(("SCARD:    \"%s\"\n", cur->szReader ? cur->szReader : "NULL"));
+			DEBUG_SCARD(("SCARD:        user: %p, state: 0x%08x, event: 0x%08x\n",
+				     cur->pvUserData, (unsigned) cur->dwCurrentState,
+				     (unsigned) cur->dwEventState));
+		}
+	}
+	else
+	{
+		rsArray = NULL;
+	}
+
+	myRsArray = SC_xmalloc(&lcHandle, dwCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
+	if (!myRsArray)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+	memset(myRsArray, 0, dwCount * sizeof(SERVER_SCARD_READERSTATE_A));
+	copyReaderState_ServerToMyPCSC(rsArray, myRsArray, (SERVER_DWORD) dwCount);
+
+	/* Workaround for a bug in pcsclite, timeout value of 0 is handled as INFINIT
+	   but is by Windows PCSC spec. used for polling current state.
+	 */
+	if (dwTimeout == 0)
+	  dwTimeout = 1;
+	rv = SCardGetStatusChange(myHContext, (MYPCSC_DWORD) dwTimeout,
+				  myRsArray, (MYPCSC_DWORD) dwCount);
+	copyReaderState_MyPCSCToServer(myRsArray, rsArray, (MYPCSC_DWORD) dwCount);
+
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success\n"));
+	}
+
+	out_uint32_le(out, dwCount);
+	out_uint32_le(out, 0x00084dd8);
+	out_uint32_le(out, dwCount);
+
+	for (i = 0, cur = rsArray; i < dwCount; i++, cur++)
+	{
+		DEBUG_SCARD(("SCARD:    \"%s\"\n", cur->szReader ? cur->szReader : "NULL"));
+		DEBUG_SCARD(("SCARD:        user: %p, state: 0x%08x, event: 0x%08x\n",
+			     cur->pvUserData, (unsigned) cur->dwCurrentState,
+			     (unsigned) cur->dwEventState));
+
+		/* Do endian swaps... */
+		cur->dwCurrentState = swap32(cur->dwCurrentState);
+		cur->dwEventState = swap32(cur->dwEventState);
+		cur->cbAtr = swap32(cur->cbAtr);
+
+		out_uint8p(out, (void *) ((unsigned char **) cur + 2),
+			   sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
+	}
+	outForceAlignment(out, 8);
+	SC_xfreeallmemory(&lcHandle);
+	return rv;
+}
+
+static MYPCSC_DWORD
+TS_SCardCancel(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hContext;
+	MYPCSC_SCARDCONTEXT myHContext;
+
+	in->p += 0x1C;
+	in_uint32_le(in, hContext);
+
+	myHContext = _scard_handle_list_get_pcsc_handle(hContext);
+
+	DEBUG_SCARD(("SCARD: SCardCancel(context: 0x%08x [0x%08lx])\n", (unsigned) hContext,
+		     (unsigned long) myHContext));
+	rv = SCardCancel(myHContext);
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success\n"));
+	}
+	outForceAlignment(out, 8);
+	return rv;
+}
+
+static MYPCSC_DWORD
+TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
+{
+	int i, j, k;
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hContext;
+	MYPCSC_SCARDCONTEXT myHContext;
+
+	/* The SCARD_ATRMASK_L struct doesn't contain any longs or DWORDs -
+	   no need to split into SERVER_ and MYPCSC_ */
+	LPSCARD_ATRMASK_L pAtrMasks, cur;
+	SERVER_DWORD atrMaskCount = 0;
+	SERVER_DWORD readerCount = 0;
+	SERVER_LPSCARD_READERSTATE_A rsArray, ResArray, rsCur;
+	MYPCSC_LPSCARD_READERSTATE_A myRsArray;
+	PMEM_HANDLE lcHandle = NULL;
+
+	in->p += 0x2C;
+	in_uint32_le(in, hContext);
+	in_uint32_le(in, atrMaskCount);
+	pAtrMasks = SC_xmalloc(&lcHandle, atrMaskCount * sizeof(SCARD_ATRMASK_L));
+	if (!pAtrMasks)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+	in_uint8a(in, pAtrMasks, atrMaskCount * sizeof(SCARD_ATRMASK_L));
+
+	in_uint32_le(in, readerCount);
+	rsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SCARD_READERSTATE));
+	if (!rsArray)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+	memset(rsArray, 0, readerCount * sizeof(SCARD_READERSTATE));
+
+	myHContext = _scard_handle_list_get_pcsc_handle(hContext);
+
+	DEBUG_SCARD(("SCARD: SCardLocateCardsByATR(context: 0x%08x [0x%08lx], atrs: %d, readers: %d)\n", (unsigned) hContext, (unsigned long) myHContext, (int) atrMaskCount, (int) readerCount));
+
+	for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++)
+	{
+		cur->cbAtr = swap32(cur->cbAtr);
+
+		DEBUG_SCARD(("SCARD:    ATR: "));
+		for (j = 0; j < pAtrMasks->cbAtr; j++)
+		{
+		DEBUG_SCARD(("%02x%c",
+				     (unsigned) (unsigned char) cur->rgbAtr[j],
+				     (j == pAtrMasks->cbAtr - 1) ? ' ' : ':'))}
+		DEBUG_SCARD(("\n"));
+		DEBUG_SCARD(("SCARD:         "));
+		for (j = 0; j < pAtrMasks->cbAtr; j++)
+		{
+		DEBUG_SCARD(("%02x%c",
+				     (unsigned) (unsigned char) cur->rgbMask[j],
+				     (j == pAtrMasks->cbAtr - 1) ? ' ' : ':'))}
+		DEBUG_SCARD(("\n"));
+	}
+
+	for (i = 0, rsCur = (SERVER_LPSCARD_READERSTATE_A) ((unsigned char **) rsArray + 2);
+	     i < readerCount; i++, rsCur++)
+	{
+		in_uint8s(in, 4);
+		in_uint8a(in, rsCur, SERVER_SCARDSTATESIZE);
+	}
+
+	ResArray = SC_xmalloc(&lcHandle, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
+	if (!ResArray)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+
+	for (i = 0, rsCur = rsArray; i < readerCount; i++, rsCur++)
+	{
+		/* Do endian swaps... */
+		rsCur->dwCurrentState = swap32(rsCur->dwCurrentState);
+		rsCur->dwEventState = swap32(rsCur->dwEventState);
+		rsCur->cbAtr = swap32(rsCur->cbAtr);
+
+		inReaderName(&lcHandle, in, (char **) &rsCur->szReader, wide);
+		DEBUG_SCARD(("SCARD:    \"%s\"\n", rsCur->szReader ? rsCur->szReader : "NULL"));
+		DEBUG_SCARD(("SCARD:        user: %p, state: 0x%08x, event: 0x%08x\n",
+			     rsCur->pvUserData, (unsigned) rsCur->dwCurrentState,
+			     (unsigned) rsCur->dwEventState));
+	}
+	memcpy(ResArray, rsArray, readerCount * sizeof(SERVER_SCARD_READERSTATE_A));
+
+	/* FIXME segfault here. */
+	myRsArray = SC_xmalloc(&lcHandle, readerCount * sizeof(MYPCSC_SCARD_READERSTATE_A));
+	if (!myRsArray)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+	copyReaderState_ServerToMyPCSC(rsArray, myRsArray, readerCount);
+	rv = SCardGetStatusChange(myHContext, 0x00000001, myRsArray, readerCount);
+	copyReaderState_MyPCSCToServer(myRsArray, rsArray, readerCount);
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success\n"));
+		cur = pAtrMasks;
+		for (i = 0, cur = pAtrMasks; i < atrMaskCount; i++, cur++)
+		{
+			for (j = 0, rsCur = rsArray; j < readerCount; j++, rsCur++)
+			{
+				RD_BOOL equal = 1;
+				for (k = 0; k < cur->cbAtr; k++)
+				{
+					if ((cur->rgbAtr[k] & cur->rgbMask[k]) !=
+					    (rsCur->rgbAtr[k] & cur->rgbMask[k]))
+					{
+						equal = 0;
+						break;
+					}
+				}
+				if (equal)
+				{
+					rsCur->dwEventState |= 0x00000040;	/* SCARD_STATE_ATRMATCH 0x00000040 */
+					memcpy(ResArray + j, rsCur, sizeof(SCARD_READERSTATE));
+					DEBUG_SCARD(("SCARD:    \"%s\"\n",
+						     rsCur->szReader ? rsCur->szReader : "NULL"));
+					DEBUG_SCARD(("SCARD:        user: %p, state: 0x%08x, event: 0x%08x\n", rsCur->pvUserData, (unsigned) rsCur->dwCurrentState, (unsigned) rsCur->dwEventState));
+				}
+			}
+		}
+	}
+
+	out_uint32_le(out, readerCount);
+	out_uint32_le(out, 0x00084dd8);
+	out_uint32_le(out, readerCount);
+
+	for (i = 0, rsCur = ResArray; i < readerCount; i++, rsCur++)
+	{
+		/* Do endian swaps... */
+		rsCur->dwCurrentState = swap32(rsCur->dwCurrentState);
+		rsCur->dwEventState = swap32(rsCur->dwEventState);
+		rsCur->cbAtr = swap32(rsCur->cbAtr);
+
+		out_uint8p(out, (void *) ((unsigned char **) rsCur + 2),
+			   sizeof(SCARD_READERSTATE) - 2 * sizeof(unsigned char *));
+	}
+
+	outForceAlignment(out, 8);
+	SC_xfreeallmemory(&lcHandle);
+	return rv;
+}
+
+static DWORD
+TS_SCardBeginTransaction(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hCard;
+	MYPCSC_SCARDCONTEXT myHCard;
+
+	in->p += 0x30;
+	in_uint32_le(in, hCard);
+	myHCard = _scard_handle_list_get_pcsc_handle(hCard);
+	DEBUG_SCARD(("SCARD: SCardBeginTransaction(hcard: 0x%08x [0x%lx])\n",
+		     (unsigned) hCard, myHCard));
+	rv = SCardBeginTransaction(myHCard);
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success\n"));
+	}
+	outForceAlignment(out, 8);
+	return rv;
+}
+
+static DWORD
+TS_SCardEndTransaction(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hCard;
+	MYPCSC_SCARDCONTEXT myHCard;
+	SERVER_DWORD dwDisposition = 0;
+
+	in->p += 0x20;
+	in_uint32_le(in, dwDisposition);
+	in->p += 0x0C;
+	in_uint32_le(in, hCard);
+
+	myHCard = _scard_handle_list_get_pcsc_handle(hCard);
+
+	DEBUG_SCARD(("SCARD: SCardEndTransaction(hcard: 0x%08x [0x%lx], disposition: 0x%08x)\n",
+		     (unsigned) hCard, (unsigned long) myHCard, (unsigned) dwDisposition));
+	rv = SCardEndTransaction(myHCard, (MYPCSC_DWORD) dwDisposition);
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success\n"));
+	}
+	outForceAlignment(out, 8);
+	return rv;
+}
+
+
+static void
+copyIORequest_MyPCSCToServer(MYPCSC_LPSCARD_IO_REQUEST src, SERVER_LPSCARD_IO_REQUEST dst)
+{
+	unsigned char *srcBytes, *dstBytes;
+	size_t bytesToCopy = src->cbPciLength - sizeof(MYPCSC_SCARD_IO_REQUEST);
+	srcBytes = ((unsigned char *) src + sizeof(MYPCSC_SCARD_IO_REQUEST));
+	dstBytes = ((unsigned char *) dst + sizeof(SERVER_SCARD_IO_REQUEST));
+	dst->dwProtocol = swap32((uint32_t) src->dwProtocol);
+	dst->cbPciLength = swap32((uint32_t) src->cbPciLength
+				  - sizeof(MYPCSC_SCARD_IO_REQUEST) +
+				  sizeof(SERVER_SCARD_IO_REQUEST));
+	memcpy(dstBytes, srcBytes, bytesToCopy);
+}
+
+static void
+copyIORequest_ServerToMyPCSC(SERVER_LPSCARD_IO_REQUEST src, MYPCSC_LPSCARD_IO_REQUEST dst)
+{
+	unsigned char *srcBytes, *dstBytes;
+	size_t bytesToCopy = src->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST);
+	srcBytes = ((unsigned char *) src + sizeof(SERVER_SCARD_IO_REQUEST));
+	dstBytes = ((unsigned char *) dst + sizeof(MYPCSC_SCARD_IO_REQUEST));
+	dst->dwProtocol = swap32(src->dwProtocol);
+	dst->cbPciLength = src->cbPciLength	/* already correct endian */
+		- sizeof(SERVER_SCARD_IO_REQUEST) + sizeof(MYPCSC_SCARD_IO_REQUEST);
+	memcpy(dstBytes, srcBytes, bytesToCopy);
+}
+
+
+static DWORD
+TS_SCardTransmit(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_DWORD map[7], linkedLen;
+	void *tmp;
+	SERVER_SCARDCONTEXT hCard;
+	MYPCSC_SCARDCONTEXT myHCard;
+	SERVER_LPSCARD_IO_REQUEST pioSendPci, pioRecvPci;
+	MYPCSC_LPSCARD_IO_REQUEST myPioSendPci, myPioRecvPci;
+	unsigned char *sendBuf = NULL, *recvBuf = NULL;
+	SERVER_DWORD cbSendLength, cbRecvLength;
+	MYPCSC_DWORD myCbRecvLength;
+	PMEM_HANDLE lcHandle = NULL;
+
+	in->p += 0x14;
+	in_uint32_le(in, map[0]);
+	in->p += 0x04;
+	in_uint32_le(in, map[1]);
+	pioSendPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
+	if (!pioSendPci)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+	in_uint8a(in, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
+	in_uint32_le(in, map[2]);
+	in_uint32_le(in, cbSendLength);
+	in_uint32_le(in, map[3]);
+	in_uint32_le(in, map[4]);
+	in_uint32_le(in, map[5]);
+	in_uint32_le(in, cbRecvLength);
+	if (map[0] & INPUT_LINKED)
+		inSkipLinked(in);
+
+	in->p += 0x04;
+	in_uint32_le(in, hCard);
+	myHCard = _scard_handle_list_get_pcsc_handle(hCard);
+
+	if (map[2] & INPUT_LINKED)
+	{
+		in_uint32_le(in, linkedLen);
+		pioSendPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
+		tmp = SC_xmalloc(&lcHandle, pioSendPci->cbPciLength);
+		if (!tmp)
+			return SC_returnNoMemoryError(&lcHandle, in, out);
+		in_uint8a(in, (void *) ((unsigned char *) tmp + sizeof(SERVER_SCARD_IO_REQUEST)),
+			  linkedLen);
+		memcpy(tmp, pioSendPci, sizeof(SERVER_SCARD_IO_REQUEST));
+		SC_xfree(&lcHandle, pioSendPci);
+		pioSendPci = tmp;
+		tmp = NULL;
+	}
+	else
+		pioSendPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
+
+	if (map[3] & INPUT_LINKED)
+	{
+		in_uint32_le(in, linkedLen);
+		sendBuf = SC_xmalloc(&lcHandle, linkedLen);
+		if (!sendBuf)
+			return SC_returnNoMemoryError(&lcHandle, in, out);
+		in_uint8a(in, sendBuf, linkedLen);
+		inRepos(in, linkedLen);
+	}
+	else
+		sendBuf = NULL;
+
+	if (cbRecvLength)
+	{
+		recvBuf = SC_xmalloc(&lcHandle, cbRecvLength);
+		if (!recvBuf)
+			return SC_returnNoMemoryError(&lcHandle, in, out);
+	}
+
+	if (map[4] & INPUT_LINKED)
+	{
+		pioRecvPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
+		if (!pioRecvPci)
+			return SC_returnNoMemoryError(&lcHandle, in, out);
+		in_uint8a(in, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
+		in_uint32_le(in, map[6]);
+		if (map[6] & INPUT_LINKED)
+		{
+			in_uint32_le(in, linkedLen);
+			pioRecvPci->cbPciLength = linkedLen + sizeof(SERVER_SCARD_IO_REQUEST);
+			tmp = SC_xmalloc(&lcHandle, pioRecvPci->cbPciLength);
+			if (!tmp)
+				return SC_returnNoMemoryError(&lcHandle, in, out);
+			in_uint8a(in,
+				  (void *) ((unsigned char *) tmp +
+					    sizeof(SERVER_SCARD_IO_REQUEST)), linkedLen);
+			memcpy(tmp, pioRecvPci, sizeof(SERVER_SCARD_IO_REQUEST));
+			SC_xfree(&lcHandle, pioRecvPci);
+			pioRecvPci = tmp;
+			tmp = NULL;
+		}
+		else
+			pioRecvPci->cbPciLength = sizeof(SERVER_SCARD_IO_REQUEST);
+	}
+	else
+		pioRecvPci = NULL;
+
+	DEBUG_SCARD(("SCARD: SCardTransmit(hcard: 0x%08x [0x%08lx], send: %d bytes, recv: %d bytes)\n", (unsigned) hCard, (unsigned long) myHCard, (int) cbSendLength, (int) cbRecvLength));
+
+	myCbRecvLength = cbRecvLength;
+	myPioSendPci = SC_xmalloc(&lcHandle,
+				  sizeof(MYPCSC_SCARD_IO_REQUEST)
+				  + pioSendPci->cbPciLength - sizeof(SERVER_SCARD_IO_REQUEST));
+	if (!myPioSendPci)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+	copyIORequest_ServerToMyPCSC(pioSendPci, myPioSendPci);
+	/* always a send, not always a recv */
+	if (pioRecvPci)
+	{
+		myPioRecvPci = SC_xmalloc(&lcHandle,
+					  sizeof(MYPCSC_SCARD_IO_REQUEST)
+					  + pioRecvPci->cbPciLength
+					  - sizeof(SERVER_SCARD_IO_REQUEST));
+		if (!myPioRecvPci)
+			return SC_returnNoMemoryError(&lcHandle, in, out);
+		copyIORequest_ServerToMyPCSC(pioRecvPci, myPioRecvPci);
+	}
+	else
+	{
+		myPioRecvPci = NULL;
+	}
+	rv = SCardTransmit(myHCard, myPioSendPci, sendBuf, (MYPCSC_DWORD) cbSendLength,
+			   myPioRecvPci, recvBuf, &myCbRecvLength);
+	cbRecvLength = myCbRecvLength;
+
+	/* FIXME: handle responses with length > 448 bytes */
+	if (cbRecvLength > 448)
+	{
+		warning("Card response limited from %d to 448 bytes!\n", cbRecvLength);
+		DEBUG_SCARD(("SCARD:    Truncated %d to %d\n", (unsigned int) cbRecvLength, 448));
+		cbRecvLength = 448;
+	}
+
+	if (pioRecvPci)
+	{
+		/*
+		 * pscs-lite mishandles this structure in some cases.
+		 * make sure we only copy it if it is valid.
+		 */
+		if (myPioRecvPci->cbPciLength >= sizeof(MYPCSC_SCARD_IO_REQUEST))
+			copyIORequest_MyPCSCToServer(myPioRecvPci, pioRecvPci);
+	}
+
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success (%d bytes)\n", (int) cbRecvLength));
+#if 0
+		if ((pioRecvPci != NULL) && (mypioRecvPci->cbPciLength > 0))
+		{
+			out_uint32_le(out, (DWORD) pioRecvPci);	/* if not NULL, this 4 bytes indicates that pioRecvPci is present */
+		}
+		else
+#endif
+			out_uint32_le(out, 0);	/* pioRecvPci 0x00; */
+
+		outBufferStart(out, cbRecvLength);	/* start of recvBuf output */
+
+#if 0
+		if ((pioRecvPci) && (mypioRecvPci->cbPciLength > 0))
+		{
+			out_uint32_le(out, mypioRecvPci->dwProtocol);
+			int len = mypioRecvPci->cbPciLength - sizeof(mypioRecvPci);
+			outBufferStartWithLimit(out, len, 12);
+			outBufferFinishWithLimit(out,
+						 (char *) ((DWORD) pioRecvPci + sizeof(pioRecvPci)),
+						 len, 12);
+		}
+#endif
+
+		outBufferFinish(out, (char *) recvBuf, cbRecvLength);
+	}
+	outForceAlignment(out, 8);
+	SC_xfreeallmemory(&lcHandle);
+	return rv;
+}
+
+static MYPCSC_DWORD
+TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hCard;
+	MYPCSC_SCARDCONTEXT myHCard;
+	SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
+	MYPCSC_DWORD state, protocol, readerLen, atrLen;
+	SERVER_DWORD dataLength;
+	PMEM_HANDLE lcHandle = NULL;
+	char *readerName;
+	unsigned char *atr;
+
+	in->p += 0x24;
+	in_uint32_le(in, dwReaderLen);
+	in_uint32_le(in, dwAtrLen);
+	in->p += 0x0C;
+	in_uint32_le(in, hCard);
+	in->p += 0x04;
+	myHCard = _scard_handle_list_get_pcsc_handle(hCard);
+	DEBUG_SCARD(("SCARD: SCardStatus(hcard: 0x%08x [0x%08lx], reader len: %d bytes, atr len: %d bytes)\n", (unsigned) hCard, (unsigned long) myHCard, (int) dwReaderLen, (int) dwAtrLen));
+
+	if (dwReaderLen <= 0 || dwReaderLen == SCARD_AUTOALLOCATE || dwReaderLen > SCARD_MAX_MEM)
+		dwReaderLen = SCARD_MAX_MEM;
+	if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
+		dwAtrLen = SCARD_MAX_MEM;
+
+#if 1
+	/*
+	 * Active client sometimes sends a readerlen *just* big enough
+	 * SCardStatus doesn't seem to like this. This is a workaround,
+	 * aka hack!
+	 */
+	dwReaderLen = 200;
+#endif
+
+	readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
+	if (!readerName)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+
+	atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
+	if (!atr)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+
+	state = dwState;
+	protocol = dwProtocol;
+	readerLen = dwReaderLen;
+	atrLen = dwAtrLen;
+	rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
+	dwAtrLen = atrLen;
+	dwReaderLen = readerLen;
+	dwProtocol = protocol;
+	dwState = state;
+
+
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+		return SC_returnCode(rv, &lcHandle, in, out);
+	}
+	else
+	{
+		int i;
+
+		DEBUG_SCARD(("SCARD: -> Success (state: 0x%08x, proto: 0x%08x)\n",
+			     (unsigned) dwState, (unsigned) dwProtocol));
+		DEBUG_SCARD(("SCARD:        Reader: \"%s\"\n", readerName ? readerName : "NULL"));
+		DEBUG_SCARD(("SCARD:        ATR: "));
+		for (i = 0; i < dwAtrLen; i++)
+		{
+			DEBUG_SCARD(("%02x%c", atr[i], (i == dwAtrLen - 1) ? ' ' : ':'));
+		}
+		DEBUG_SCARD(("\n"));
+
+		if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
+			dwState = 0x00000006;
+		else
+#if 0
+		if (dwState & SCARD_SPECIFIC)
+			dwState = 0x00000006;
+		else if (dwState & SCARD_NEGOTIABLE)
+			dwState = 0x00000005;
+		else
+#endif
+		if (dwState & SCARD_POWERED)
+			dwState = 0x00000004;
+		else if (dwState & SCARD_SWALLOWED)
+			dwState = 0x00000003;
+		else if (dwState & SCARD_PRESENT)
+			dwState = 0x00000002;
+		else if (dwState & SCARD_ABSENT)
+			dwState = 0x00000001;
+		else
+			dwState = 0x00000000;
+
+		void *p_len1 = out->p;
+		out_uint32_le(out, dwReaderLen);
+		out_uint32_le(out, 0x00020000);
+		out_uint32_le(out, dwState);
+		out_uint32_le(out, dwProtocol);
+		out_uint8p(out, atr, dwAtrLen);
+		if (dwAtrLen < 32)
+		{
+			out_uint8s(out, 32 - dwAtrLen);
+		}
+		out_uint32_le(out, dwAtrLen);
+
+		void *p_len2 = out->p;
+		out_uint32_le(out, dwReaderLen);
+		dataLength = outString(out, readerName, wide);
+		dataLength += outString(out, "\0", wide);
+		outRepos(out, dataLength);
+		void *psave = out->p;
+		out->p = p_len1;
+		out_uint32_le(out, dataLength);
+		out->p = p_len2;
+		out_uint32_le(out, dataLength);
+		out->p = psave;
+	}
+	outForceAlignment(out, 8);
+	SC_xfreeallmemory(&lcHandle);
+	return rv;
+}
+
+static MYPCSC_DWORD
+TS_SCardState(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hCard;
+	MYPCSC_SCARDCONTEXT myHCard;
+	SERVER_DWORD dwState = 0, dwProtocol = 0, dwReaderLen, dwAtrLen;
+	MYPCSC_DWORD state, protocol, readerLen, atrLen;
+	PMEM_HANDLE lcHandle = NULL;
+	char *readerName;
+	unsigned char *atr;
+
+	in->p += 0x24;
+	in_uint32_le(in, dwAtrLen);
+	in->p += 0x0C;
+	in_uint32_le(in, hCard);
+	in->p += 0x04;
+	myHCard = _scard_handle_list_get_pcsc_handle(hCard);
+
+	DEBUG_SCARD(("SCARD: SCardState(hcard: 0x%08x [0x%08lx], atr len: %d bytes)\n",
+		     (unsigned) hCard, (unsigned long) myHCard, (int) dwAtrLen));
+
+	dwReaderLen = SCARD_MAX_MEM;
+	if (dwAtrLen <= 0 || dwAtrLen == SCARD_AUTOALLOCATE || dwAtrLen > SCARD_MAX_MEM)
+		dwAtrLen = SCARD_MAX_MEM;
+
+	readerName = SC_xmalloc(&lcHandle, dwReaderLen + 2);
+	if (!readerName)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+
+	atr = SC_xmalloc(&lcHandle, dwAtrLen + 1);
+	if (!atr)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+
+	state = dwState;
+	protocol = dwProtocol;
+	readerLen = dwReaderLen;
+	atrLen = dwAtrLen;
+	rv = SCardStatus(myHCard, readerName, &readerLen, &state, &protocol, atr, &atrLen);
+	dwAtrLen = atrLen;
+	dwReaderLen = readerLen;
+	dwProtocol = protocol;
+	dwState = state;
+
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+		return SC_returnCode(rv, &lcHandle, in, out);
+	}
+	else
+	{
+		int i;
+
+		DEBUG_SCARD(("SCARD: -> Success (state: 0x%08x, proto: 0x%08x)\n",
+			     (unsigned) dwState, (unsigned) dwProtocol));
+		DEBUG_SCARD(("SCARD:        ATR: "));
+		for (i = 0; i < dwAtrLen; i++)
+		{
+			DEBUG_SCARD(("%02x%c", atr[i], (i == dwAtrLen - 1) ? ' ' : ':'));
+		}
+		DEBUG_SCARD(("\n"));
+
+		if (dwState & (SCARD_SPECIFIC | SCARD_NEGOTIABLE))
+			dwState = 0x00000006;
+		else
+#if 0
+		if (dwState & SCARD_SPECIFIC)
+			dwState = 0x00000006;
+		else if (dwState & SCARD_NEGOTIABLE)
+			dwState = 0x00000005;
+		else
+#endif
+		if (dwState & SCARD_POWERED)
+			dwState = 0x00000004;
+		else if (dwState & SCARD_SWALLOWED)
+			dwState = 0x00000003;
+		else if (dwState & SCARD_PRESENT)
+			dwState = 0x00000002;
+		else if (dwState & SCARD_ABSENT)
+			dwState = 0x00000001;
+		else
+			dwState = 0x00000000;
+
+		out_uint32_le(out, dwState);
+		out_uint32_le(out, dwProtocol);
+		out_uint32_le(out, dwAtrLen);
+		out_uint32_le(out, 0x00000001);
+		out_uint32_le(out, dwAtrLen);
+		out_uint8p(out, atr, dwAtrLen);
+		outRepos(out, dwAtrLen);
+	}
+	outForceAlignment(out, 8);
+	SC_xfreeallmemory(&lcHandle);
+	return rv;
+}
+
+
+
+#ifndef WITH_PCSC120
+
+/* Currently unused */
+#if 0
+static MYPCSC_DWORD
+TS_SCardListReaderGroups(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hContext;
+	MYPCSC_SCARDCONTEXT myHContext;
+	SERVER_DWORD dwGroups;
+	MYPCSC_DWORD groups;
+	char *szGroups;
+	PMEM_HANDLE lcHandle = NULL;
+
+	in->p += 0x20;
+	in_uint32_le(in, dwGroups);
+	in->p += 0x04;
+	in_uint32_le(in, hContext);
+
+	myHContext = _scard_handle_list_get_pcsc_handle(hContext);
+
+	DEBUG_SCARD(("SCARD: SCardListReaderGroups(context: 0x%08x [0x%08lx], groups: %d)\n",
+		     (unsigned) hContext, (unsigned int) myHContext, (int) dwGroups));
+
+	if (dwGroups <= 0 || dwGroups == SCARD_AUTOALLOCATE || dwGroups > SCARD_MAX_MEM)
+		dwGroups = SCARD_MAX_MEM;
+
+	szGroups = SC_xmalloc(&lcHandle, dwGroups);
+	if (!szGroups)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+
+	groups = dwGroups;
+	rv = SCardListReaderGroups(myHContext, szGroups, &groups);
+	dwGroups = groups;
+
+	if (rv)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+		return SC_returnCode(rv, &lcHandle, in, out);
+	}
+	else
+	{
+		int i;
+		char *cur;
+
+		DEBUG_SCARD(("SCARD: -> Success\n"));
+		for (i = 0, cur = szGroups; i < dwGroups; i++, cur += strlen(cur) + 1)
+		{
+			DEBUG_SCARD(("SCARD:    %s\n", cur));
+		}
+	}
+
+
+	out_uint32_le(out, dwGroups);
+	out_uint32_le(out, 0x00200000);
+	out_uint32_le(out, dwGroups);
+	out_uint8a(out, szGroups, dwGroups);
+	outRepos(out, dwGroups);
+	out_uint32_le(out, 0x00000000);
+
+	outForceAlignment(out, 8);
+	SC_xfreeallmemory(&lcHandle);
+	return rv;
+}
+#endif
+
+static MYPCSC_DWORD
+TS_SCardGetAttrib(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hCard;
+	MYPCSC_SCARDCONTEXT myHCard;
+	SERVER_DWORD dwAttrId, dwAttrLen;
+	MYPCSC_DWORD attrLen;
+	unsigned char *pbAttr;
+	PMEM_HANDLE lcHandle = NULL;
+
+	in->p += 0x20;
+	in_uint32_le(in, dwAttrId);
+	in->p += 0x04;
+	in_uint32_le(in, dwAttrLen);
+	in->p += 0x0C;
+	in_uint32_le(in, hCard);
+	myHCard = _scard_handle_list_get_pcsc_handle(hCard);
+
+	DEBUG_SCARD(("SCARD: SCardGetAttrib(hcard: 0x%08x [0x%08lx], attrib: 0x%08x (%d bytes))\n",
+		     (unsigned) hCard, (unsigned long) myHCard,
+		     (unsigned) dwAttrId, (int) dwAttrLen));
+
+	if (dwAttrLen > MAX_BUFFER_SIZE)
+		dwAttrLen = MAX_BUFFER_SIZE;
+
+
+	if (dwAttrLen > SCARD_AUTOALLOCATE)
+		pbAttr = NULL;
+	else if ((dwAttrLen < 0) || (dwAttrLen > SCARD_MAX_MEM))
+	{
+		dwAttrLen = (SERVER_DWORD) SCARD_AUTOALLOCATE;
+		pbAttr = NULL;
+	}
+	else
+	{
+		pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
+		if (!pbAttr)
+			return SC_returnNoMemoryError(&lcHandle, in, out);
+	}
+
+	attrLen = dwAttrLen;
+	rv = SCardGetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, &attrLen);
+	dwAttrLen = attrLen;
+
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+		return SC_returnCode(rv, &lcHandle, in, out);
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success (%d bytes)\n", (int) dwAttrLen));
+
+		out_uint32_le(out, dwAttrLen);
+		out_uint32_le(out, 0x00000200);
+		out_uint32_le(out, dwAttrLen);
+		if (!pbAttr)
+		{
+			out_uint8s(out, dwAttrLen);
+		}
+		else
+		{
+			out_uint8p(out, pbAttr, dwAttrLen);
+		}
+		outRepos(out, dwAttrLen);
+		out_uint32_le(out, 0x00000000);
+	}
+	outForceAlignment(out, 8);
+	return rv;
+}
+
+/* Currently unused */
+#if 0
+static MYPCSC_DWORD
+TS_SCardSetAttrib(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hCard;
+	MYPCSC_SCARDCONTEXT myHCard;
+	SERVER_DWORD dwAttrId;
+	SERVER_DWORD dwAttrLen;
+	unsigned char *pbAttr;
+	PMEM_HANDLE lcHandle = NULL;
+
+	in->p += 0x20;
+	in_uint32_le(in, dwAttrId);
+	in->p += 0x04;
+	in_uint32_le(in, dwAttrLen);
+	in->p += 0x0C;
+	in_uint32_le(in, hCard);
+	myHCard = scHandleToMyPCSC(hCard);
+
+	DEBUG_SCARD(("SCARD: SCardSetAttrib(hcard: 0x%08x [0x%08lx], attrib: 0x%08x (%d bytes))\n",
+		     (unsigned) hCard, (unsigned long) myHCard,
+		     (unsigned) dwAttrId, (int) dwAttrLen));
+
+	if (dwAttrLen > MAX_BUFFER_SIZE)
+		dwAttrLen = MAX_BUFFER_SIZE;
+
+	pbAttr = SC_xmalloc(&lcHandle, dwAttrLen);
+	if (!pbAttr)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+
+	in_uint8a(in, pbAttr, dwAttrLen);
+	rv = SCardSetAttrib(myHCard, (MYPCSC_DWORD) dwAttrId, pbAttr, (MYPCSC_DWORD) dwAttrLen);
+
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success\n"));
+	}
+
+	out_uint32_le(out, 0x00000000);
+	out_uint32_le(out, 0x00000200);
+	out_uint32_le(out, 0x00000000);
+	out_uint32_le(out, 0x00000000);
+	outForceAlignment(out, 8);
+	SC_xfreeallmemory(&lcHandle);
+	return rv;
+}
+#endif
+
+#endif
+
+static MYPCSC_DWORD
+TS_SCardControl(STREAM in, STREAM out)
+{
+	MYPCSC_DWORD rv;
+	SERVER_SCARDCONTEXT hContext;
+	MYPCSC_SCARDCONTEXT myHContext;
+	SERVER_SCARDHANDLE hCard;
+	MYPCSC_SCARDHANDLE myHCard;
+	SERVER_DWORD map[3];
+	SERVER_DWORD dwControlCode;
+	unsigned char *pInBuffer, *pOutBuffer;
+	SERVER_DWORD nInBufferSize, nOutBufferSize, nOutBufferRealSize, nBytesReturned;
+	MYPCSC_DWORD sc_nBytesReturned;
+	PMEM_HANDLE lcHandle = NULL;
+
+	pInBuffer = NULL;
+	pOutBuffer = NULL;
+
+	in->p += 0x14;
+	in_uint32_le(in, map[0]);
+	in->p += 0x04;
+	in_uint32_le(in, map[1]);
+	in_uint32_le(in, dwControlCode);
+	in_uint32_le(in, nInBufferSize);
+	in_uint32_le(in, map[2]);
+	in->p += 0x04;
+	in_uint32_le(in, nOutBufferSize);
+	in->p += 0x04;
+	in_uint32_le(in, hContext);
+	in->p += 0x04;
+	in_uint32_le(in, hCard);
+	if (map[2] & INPUT_LINKED)
+	{
+		/* read real input size */
+		in_uint32_le(in, nInBufferSize);
+		if (nInBufferSize > 0)
+		{
+			pInBuffer = SC_xmalloc(&lcHandle, nInBufferSize);
+			if (!pInBuffer)
+				return SC_returnNoMemoryError(&lcHandle, in, out);
+			in_uint8a(in, pInBuffer, nInBufferSize);
+		}
+	}
+
+	myHCard = _scard_handle_list_get_pcsc_handle(hCard);
+	myHContext = _scard_handle_list_get_pcsc_handle(hContext);
+
+	DEBUG_SCARD(("SCARD: SCardControl(context: 0x%08x [0x%08lx], hcard: 0x%08x [0x%08lx], code: 0x%08x, in: %d bytes, out: %d bytes)\n", (unsigned) hContext, (unsigned long) myHContext, (unsigned) hCard, (unsigned long) myHCard, (unsigned) dwControlCode, (int) nInBufferSize, (int) nOutBufferSize));
+
+	/* Is this a proper Windows smart card ioctl? */
+	if ((dwControlCode & 0xffff0000) == (49 << 16))
+	{
+		/* Translate to local encoding */
+		dwControlCode = (dwControlCode & 0x3ffc) >> 2;
+		dwControlCode = SCARD_CTL_CODE(dwControlCode);
+	}
+	else
+	{
+		warning("Bogus smart card control code 0x%08x\n", dwControlCode);
+	}
+
+#if 0
+	if (nOutBufferSize > 0)
+	{
+		nOutBufferRealSize = nOutBufferSize;
+	}
+	else
+#endif
+		nOutBufferRealSize = 1024;
+
+	nBytesReturned = nOutBufferRealSize;
+
+	nBytesReturned = nOutBufferRealSize;
+	pOutBuffer = SC_xmalloc(&lcHandle, nOutBufferRealSize);
+	if (!pOutBuffer)
+		return SC_returnNoMemoryError(&lcHandle, in, out);
+
+	sc_nBytesReturned = nBytesReturned;
+
+#ifdef WITH_PCSC120
+	rv = SCardControl(myHCard, pInBuffer, (MYPCSC_DWORD) nInBufferSize, pOutBuffer,
+			  &sc_nBytesReturned);
+#else
+	rv = SCardControl(myHCard, (MYPCSC_DWORD) dwControlCode, pInBuffer,
+			  (MYPCSC_DWORD) nInBufferSize, pOutBuffer,
+			  (MYPCSC_DWORD) nOutBufferRealSize, &sc_nBytesReturned);
+#endif
+	nBytesReturned = sc_nBytesReturned;
+
+	if (rv != SCARD_S_SUCCESS)
+	{
+		DEBUG_SCARD(("SCARD: -> Failure: %s (0x%08x)\n",
+			     pcsc_stringify_error(rv), (unsigned int) rv));
+	}
+	else
+	{
+		DEBUG_SCARD(("SCARD: -> Success (out: %d bytes)\n", (int) nBytesReturned));
+	}
+
+#ifdef PCSCLITE_VERSION_NUMBER
+	if (dwControlCode == SCARD_CTL_CODE(3400))
+	{
+		int i;
+		SERVER_DWORD cc;
+
+		for (i = 0; i < nBytesReturned / 6; i++)
+		{
+			memcpy(&cc, pOutBuffer + 2 + i * 6, 4);
+			cc = ntohl(cc);
+			cc = cc - 0x42000000;
+			cc = (49 << 16) | (cc << 2);
+			cc = htonl(cc);
+			memcpy(pOutBuffer + 2 + i * 6, &cc, 4);
+		}
+	}
+#endif
+
+	out_uint32_le(out, nBytesReturned);
+	out_uint32_le(out, 0x00000004);
+	out_uint32_le(out, nBytesReturned);
+	if (nBytesReturned > 0)
+	{
+		out_uint8p(out, pOutBuffer, nBytesReturned);
+		outRepos(out, nBytesReturned);
+	}
+
+	outForceAlignment(out, 8);
+	SC_xfreeallmemory(&lcHandle);
+	return rv;
+}
+
+static MYPCSC_DWORD
+TS_SCardAccessStartedEvent(STREAM in, STREAM out)
+{
+	DEBUG_SCARD(("SCARD: SCardAccessStartedEvent()\n"));
+	out_uint8s(out, 8);
+	return SCARD_S_SUCCESS;
+}
+
+
+static RD_NTSTATUS
+scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
+{
+	SERVER_DWORD Result = 0x00000000;
+	unsigned char *psize, *pend, *pStatusCode;
+	SERVER_DWORD addToEnd = 0;
+
+	/* Processing request */
+
+	out_uint32_le(out, 0x00081001);	/* Header lines */
+	out_uint32_le(out, 0xCCCCCCCC);
+	psize = out->p;
+	out_uint32_le(out, 0x00000000);	/* Size of data portion */
+	out_uint32_le(out, 0x00000000);	/* Zero bytes (may be usefull) */
+	pStatusCode = out->p;
+	out_uint32_le(out, 0x00000000);	/* Status Code */
+
+	switch (request)
+	{
+			/* SCardEstablishContext */
+		case SC_ESTABLISH_CONTEXT:
+			{
+				Result = (SERVER_DWORD) TS_SCardEstablishContext(in, out);
+				break;
+			}
+			/* SCardReleaseContext */
+		case SC_RELEASE_CONTEXT:
+			{
+				Result = (SERVER_DWORD) TS_SCardReleaseContext(in, out);
+				break;
+			}
+			/* SCardIsValidContext */
+		case SC_IS_VALID_CONTEXT:
+			{
+				Result = (SERVER_DWORD) TS_SCardIsValidContext(in, out);
+				break;
+			}
+			/* SCardListReaders */
+		case SC_LIST_READERS:	/* SCardListReadersA */
+		case SC_LIST_READERS + 4:	/* SCardListReadersW */
+			{
+				RD_BOOL wide = request != SC_LIST_READERS;
+				Result = (SERVER_DWORD) TS_SCardListReaders(in, out, wide);
+				break;
+			}
+			/* ScardConnect */
+		case SC_CONNECT:	/* ScardConnectA */
+		case SC_CONNECT + 4:	/* SCardConnectW */
+			{
+				RD_BOOL wide = request != SC_CONNECT;
+				Result = (SERVER_DWORD) TS_SCardConnect(in, out, wide);
+				break;
+			}
+			/* ScardReconnect */
+		case SC_RECONNECT:
+			{
+				Result = (SERVER_DWORD) TS_SCardReconnect(in, out);
+				break;
+			}
+			/* ScardDisconnect */
+		case SC_DISCONNECT:
+			{
+				Result = (SERVER_DWORD) TS_SCardDisconnect(in, out);
+				break;
+			}
+			/* ScardGetStatusChange */
+		case SC_GET_STATUS_CHANGE:	/* SCardGetStatusChangeA */
+		case SC_GET_STATUS_CHANGE + 4:	/* SCardGetStatusChangeW */
+			{
+				RD_BOOL wide = request != SC_GET_STATUS_CHANGE;
+				Result = (SERVER_DWORD) TS_SCardGetStatusChange(in, out, wide);
+				break;
+			}
+			/* SCardCancel */
+		case SC_CANCEL:
+			{
+				Result = (SERVER_DWORD) TS_SCardCancel(in, out);
+				break;
+			}
+			/* SCardLocateCardsByATR */
+		case SC_LOCATE_CARDS_BY_ATR:	/* SCardLocateCardsByATRA */
+		case SC_LOCATE_CARDS_BY_ATR + 4:	/* SCardLocateCardsByATRW */
+			{
+				RD_BOOL wide = request != SC_LOCATE_CARDS_BY_ATR;
+				Result = (SERVER_DWORD) TS_SCardLocateCardsByATR(in, out, wide);
+				break;
+			}
+			/* SCardBeginTransaction */
+		case SC_BEGIN_TRANSACTION:
+			{
+				Result = (SERVER_DWORD) TS_SCardBeginTransaction(in, out);
+				break;
+			}
+			/* SCardBeginTransaction */
+		case SC_END_TRANSACTION:
+			{
+				Result = (SERVER_DWORD) TS_SCardEndTransaction(in, out);
+				break;
+			}
+			/* ScardTransmit */
+		case SC_TRANSMIT:
+			{
+				Result = (SERVER_DWORD) TS_SCardTransmit(in, out);
+				break;
+			}
+			/* SCardControl */
+		case SC_CONTROL:
+			{
+				Result = (SERVER_DWORD) TS_SCardControl(in, out);
+				break;
+			}
+			/* SCardGetAttrib */
+#ifndef WITH_PCSC120
+		case SC_GETATTRIB:
+			{
+				Result = (SERVER_DWORD) TS_SCardGetAttrib(in, out);
+				break;
+			}
+#endif
+		case SC_ACCESS_STARTED_EVENT:
+			{
+				Result = (SERVER_DWORD) TS_SCardAccessStartedEvent(in, out);
+				break;
+			}
+		case SC_STATUS:	/* SCardStatusA */
+		case SC_STATUS + 4:	/* SCardStatusW */
+			{
+				RD_BOOL wide = request != SC_STATUS;
+				Result = (SERVER_DWORD) TS_SCardStatus(in, out, wide);
+				break;
+			}
+		case SC_STATE:	/* SCardState */
+			{
+				Result = (SERVER_DWORD) TS_SCardState(in, out);
+				break;
+			}
+		default:
+			{
+				warning("SCARD: Unknown function %d\n", (int) request);
+				Result = 0x80100014;
+				out_uint8s(out, 256);
+				break;
+			}
+	}
+
+#if 0
+	out_uint32_le(out, 0x00000000);
+#endif
+	/* Setting modified variables */
+	pend = out->p;
+	/* setting data size */
+	out->p = psize;
+	out_uint32_le(out, pend - psize - 16);
+	/* setting status code */
+	out->p = pStatusCode;
+	out_uint32_le(out, Result);
+	/* finish */
+	out->p = pend;
+
+	addToEnd = (pend - pStatusCode) % 16;
+	if (addToEnd < 16 && addToEnd > 0)
+	{
+		out_uint8s(out, addToEnd);
+	}
+
+	return RD_STATUS_SUCCESS;
+}
+
+/* Thread functions */
+
+static STREAM
+duplicateStream(PMEM_HANDLE * handle, STREAM s, uint32 buffer_size, RD_BOOL isInputStream)
+{
+	STREAM d = SC_xmalloc(handle, sizeof(struct stream));
+	if (d != NULL)
+	{
+		if (isInputStream)
+			d->size = (size_t) (s->end) - (size_t) (s->data);
+		else if (buffer_size < s->size)
+			d->size = s->size;
+		else
+			d->size = buffer_size;
+
+		d->data = SC_xmalloc(handle, d->size);
+
+		d->end = (void *) ((size_t) (d->data) + (size_t) (s->end) - (size_t) (s->data));
+		d->p = (void *) ((size_t) (d->data) + (size_t) (s->p) - (size_t) (s->data));
+		d->iso_hdr =
+			(void *) ((size_t) (d->data) + (size_t) (s->iso_hdr) - (size_t) (s->data));
+		d->mcs_hdr =
+			(void *) ((size_t) (d->data) + (size_t) (s->mcs_hdr) - (size_t) (s->data));
+		d->sec_hdr =
+			(void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
+		d->sec_hdr =
+			(void *) ((size_t) (d->data) + (size_t) (s->sec_hdr) - (size_t) (s->data));
+		d->rdp_hdr =
+			(void *) ((size_t) (d->data) + (size_t) (s->rdp_hdr) - (size_t) (s->data));
+		d->channel_hdr =
+			(void *) ((size_t) (d->data) + (size_t) (s->channel_hdr) -
+				  (size_t) (s->data));
+		if (isInputStream)
+			memcpy(d->data, s->data, (size_t) (s->end) - (size_t) (s->data));
+		else
+			memcpy(d->data, s->data, (size_t) (s->p) - (size_t) (s->data));
+	}
+	return d;
+}
+
+/* Currently unused */
+#if 0
+static void
+freeStream(PMEM_HANDLE * handle, STREAM s)
+{
+	if (s != NULL)
+	{
+		if (s->data != NULL)
+			SC_xfree(handle, s->data);
+		SC_xfree(handle, s);
+	}
+}
+#endif
+
+static PSCThreadData
+SC_addToQueue(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
+{
+	PMEM_HANDLE lcHandle = NULL;
+	PSCThreadData data = SC_xmalloc(&lcHandle, sizeof(TSCThreadData));
+
+	if (!data)
+		return NULL;
+	else
+	{
+		data->memHandle = lcHandle;
+		data->device = curDevice;
+		data->id = curId;
+		data->epoch = curEpoch;
+		data->handle = handle;
+		data->request = request;
+		data->in = duplicateStream(&(data->memHandle), in, 0, SC_TRUE);
+		if (data->in == NULL)
+		{
+			SC_xfreeallmemory(&(data->memHandle));
+			return NULL;
+		}
+		data->out =
+			duplicateStream(&(data->memHandle), out, OUT_STREAM_SIZE + curBytesOut,
+					SC_FALSE);
+		if (data->out == NULL)
+		{
+			SC_xfreeallmemory(&(data->memHandle));
+			return NULL;
+		}
+		data->next = NULL;
+
+		pthread_mutex_lock(&queueAccess);
+
+		if (queueLast)
+			queueLast->next = data;
+		queueLast = data;
+		if (!queueFirst)
+			queueFirst = data;
+
+		pthread_cond_broadcast(&queueEmpty);
+		pthread_mutex_unlock(&queueAccess);
+	}
+	return data;
+}
+
+static void
+SC_destroyThreadData(PSCThreadData data)
+{
+	if (data)
+	{
+		PMEM_HANDLE handle = data->memHandle;
+		SC_xfreeallmemory(&handle);
+	}
+}
+
+static PSCThreadData
+SC_getNextInQueue()
+{
+	PSCThreadData Result = NULL;
+
+	pthread_mutex_lock(&queueAccess);
+
+	while (queueFirst == NULL)
+		pthread_cond_wait(&queueEmpty, &queueAccess);
+
+	Result = queueFirst;
+	queueFirst = queueFirst->next;
+	if (!queueFirst)
+	{
+		queueLast = NULL;
+	}
+	Result->next = NULL;
+
+	pthread_mutex_unlock(&queueAccess);
+
+	return Result;
+}
+
+static void
+SC_deviceControl(PSCThreadData data)
+{
+	size_t buffer_len = 0;
+	scard_device_control(data->handle, data->request, data->in, data->out);
+	buffer_len = (size_t) data->out->p - (size_t) data->out->data;
+
+	/* if iorequest belongs to another epoch, don't send response
+	   back to server due to it's considered as abdonend.
+	 */
+	if (data->epoch == curEpoch)
+		rdpdr_send_completion(data->device, data->id, 0, buffer_len, data->out->data,
+				      buffer_len);
+
+	SC_destroyThreadData(data);
+}
+
+
+static void *
+thread_function(PThreadListElement listElement)
+{
+	pthread_mutex_lock(&listElement->busy);
+	while (1)
+	{
+		while (listElement->data == NULL)
+			pthread_cond_wait(&listElement->nodata, &listElement->busy);
+
+		SC_deviceControl(listElement->data);
+		listElement->data = NULL;
+	}
+	pthread_mutex_unlock(&listElement->busy);
+
+	pthread_exit(NULL);
+	return NULL;
+}
+
+static void
+SC_handleRequest(PSCThreadData data)
+{
+	int Result = 0;
+	PThreadListElement cur;
+
+	for (cur = threadList; cur != NULL; cur = cur->next)
+	{
+		if (cur->data == NULL)
+		{
+			pthread_mutex_lock(&cur->busy);
+			/* double check with lock held.... */
+			if (cur->data != NULL)
+			{
+				pthread_mutex_unlock(&cur->busy);
+				continue;
+			}
+
+			/* Wake up thread */
+			cur->data = data;
+			pthread_cond_broadcast(&cur->nodata);
+			pthread_mutex_unlock(&cur->busy);
+			return;
+		}
+	}
+
+	cur = SC_xmalloc(&threadListHandle, sizeof(TThreadListElement));
+	if (!cur)
+		return;
+
+	threadCount++;
+
+	pthread_mutex_init(&cur->busy, NULL);
+	pthread_cond_init(&cur->nodata, NULL);
+	cur->data = data;
+
+	Result = pthread_create(&cur->thread, NULL, (void *(*)(void *)) thread_function, cur);
+	if (0 != Result)
+	{
+		error("[THREAD CREATE ERROR 0x%.8x]\n", Result);
+		SC_xfree(&threadListHandle, cur);
+		SC_destroyThreadData(data);
+		data = NULL;
+	}
+	cur->next = threadList;
+	threadList = cur;
+}
+
+static void *
+queue_handler_function(void *data)
+{
+	PSCThreadData cur_data = NULL;
+	while (1)
+	{
+		cur_data = SC_getNextInQueue();
+		switch (cur_data->request)
+		{
+			case SC_ESTABLISH_CONTEXT:
+			case SC_RELEASE_CONTEXT:
+				{
+					SC_deviceControl(cur_data);
+					break;
+				}
+			default:
+				{
+					SC_handleRequest(cur_data);
+					break;
+				}
+		}
+	}
+	return NULL;
+}
+
+static RD_NTSTATUS
+thread_wrapper(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
+{
+	if (SC_addToQueue(handle, request, in, out))
+		return RD_STATUS_PENDING | 0xC0000000;
+	else
+		return RD_STATUS_NO_SUCH_FILE;
+}
+
+DEVICE_FNS scard_fns = {
+	scard_create,
+	scard_close,
+	scard_read,
+	scard_write,
+	thread_wrapper
+};
+#endif /* MAKE_PROTO */
+
+void
+scard_lock(int lock)
+{
+	if (!scard_mutex)
+	{
+		int i;
+
+		scard_mutex =
+			(pthread_mutex_t **) xmalloc(sizeof(pthread_mutex_t *) * SCARD_LOCK_LAST);
+
+		for (i = 0; i < SCARD_LOCK_LAST; i++)
+		{
+			scard_mutex[i] = NULL;
+		}
+	}
+
+	if (!scard_mutex[lock])
+	{
+		scard_mutex[lock] = (pthread_mutex_t *) xmalloc(sizeof(pthread_mutex_t));
+		pthread_mutex_init(scard_mutex[lock], NULL);
+	}
+
+	pthread_mutex_lock(scard_mutex[lock]);
+}
+
+void
+scard_unlock(int lock)
+{
+	pthread_mutex_unlock(scard_mutex[lock]);
+}
+
+void
+scard_reset_state()
+{
+	curDevice = 0;
+	curId = 0;
+	curBytesOut = 0;
+
+	queueFirst = queueLast = NULL;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/scard.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/scard.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/scard.h	(revision 55121)
@@ -0,0 +1,173 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   Smart Card support
+   Copyright (C) Alexi Volkov <alexi@myrealbox.com> 2006
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include "proto.h"
+
+/*************************************************************************/
+/* these are the additional types needed to split out 64-vs-32-bit APIs  */
+/*                                                                       */
+
+/* The point of all of this is to avoid patching the existing smartcard
+ * infrastructure (PC/SC Lite, libmusclecard+libmusclepkcs11 or CoolKey, any
+ * other apps linking against any of these) because the need for patches
+ * spreads without limit. The alternative is to patch the heck out of rdesktop,
+ * which is already being done anyway.
+ *
+ * - jared.jennings@eglin.af.mil, 2 Aug 2006
+ */
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+/* A DWORD when dealing with the smartcard stuff. Could be 32 bits or 64. */
+typedef DWORD MYPCSC_DWORD;
+/* A DWORD when talking to the server. Must be exactly 32 bits all the time.*/
+typedef uint32_t SERVER_DWORD;
+
+typedef SCARDCONTEXT MYPCSC_SCARDCONTEXT;
+typedef SCARDHANDLE MYPCSC_SCARDHANDLE;
+typedef uint32_t SERVER_SCARDCONTEXT;
+typedef uint32_t SERVER_SCARDHANDLE;
+
+typedef SCARD_READERSTATE MYPCSC_SCARD_READERSTATE_A, *MYPCSC_LPSCARD_READERSTATE_A;
+
+typedef struct
+{
+	const char *szReader;
+	void *pvUserData;
+	SERVER_DWORD dwCurrentState;
+	SERVER_DWORD dwEventState;
+	SERVER_DWORD cbAtr;
+	unsigned char rgbAtr[36];
+}
+SERVER_SCARD_READERSTATE_A;
+
+typedef SERVER_SCARD_READERSTATE_A *SERVER_LPSCARD_READERSTATE_A;
+
+#define SERVER_SCARDSTATESIZE              (sizeof(SERVER_SCARD_READERSTATE_A) - sizeof(const char *) - sizeof(void *))
+#define MYPCSC_SCARDSTATESIZE              (sizeof(MYPCSC_SCARD_READERSTATE_A) - sizeof(const char *) - sizeof(void *))
+
+typedef struct _SERVER_SCARD_IO_REQUEST
+{
+	SERVER_DWORD dwProtocol;	/* Protocol identifier */
+	SERVER_DWORD cbPciLength;	/* Protocol Control Inf Length */
+}
+SERVER_SCARD_IO_REQUEST, *SERVER_LPSCARD_IO_REQUEST;
+
+typedef SCARD_IO_REQUEST MYPCSC_SCARD_IO_REQUEST;
+typedef LPSCARD_IO_REQUEST MYPCSC_LPSCARD_IO_REQUEST;
+
+
+/*                                                                       */
+/*                                                                       */
+/*************************************************************************/
+
+
+#define	SC_TRUE                     1
+#define SC_FALSE                    0
+
+#define SC_ESTABLISH_CONTEXT        0x00090014	/* EstablishContext */
+#define SC_RELEASE_CONTEXT          0x00090018	/* ReleaseContext */
+#define SC_IS_VALID_CONTEXT         0x0009001C	/* IsValidContext */
+#define SC_LIST_READER_GROUPS       0x00090020	/* ListReaderGroups */
+#define SC_LIST_READERS             0x00090028	/* ListReadersA */
+#define SC_INTRODUCE_READER_GROUP   0x00090050	/* IntroduceReaderGroup */
+#define SC_FORGET_READER_GROUP      0x00090058	/* ForgetReader */
+#define SC_INTRODUCE_READER         0x00090060	/* IntroduceReader */
+#define SC_FORGET_READER            0x00090068	/* IntroduceReader */
+#define SC_ADD_READER_TO_GROUP      0x00090070	/* AddReaderToGroup */
+#define SC_REMOVE_READER_FROM_GROUP 0x00090078	/* RemoveReaderFromGroup */
+#define SC_CONNECT                  0x000900AC	/* ConnectA */
+#define SC_RECONNECT                0x000900B4	/* Reconnect */
+#define SC_DISCONNECT               0x000900B8	/* Disconnect */
+#define SC_GET_STATUS_CHANGE        0x000900A0	/* GetStatusChangeA */
+#define SC_CANCEL                   0x000900A8	/* Cancel */
+#define SC_BEGIN_TRANSACTION        0x000900BC	/* BeginTransaction */
+#define SC_END_TRANSACTION          0x000900C0	/* EndTransaction */
+#define SC_STATE		    0x000900C4	/* State */
+#define SC_STATUS                   0x000900C8	/* StatusA */
+#define SC_TRANSMIT                 0x000900D0	/* Transmit */
+#define SC_CONTROL                  0x000900D4	/* Control */
+#define SC_GETATTRIB                0x000900D8	/* GetAttrib */
+#define SC_SETATTRIB                0x000900DC	/* SetAttrib */
+#define SC_ACCESS_STARTED_EVENT	    0x000900E0	/* SCardAccessStartedEvent */
+#define SC_LOCATE_CARDS_BY_ATR      0x000900E8	/* LocateCardsByATR */
+
+/* #define INPUT_LINKED                0x00020000 */
+#define INPUT_LINKED                0xFFFFFFFF
+
+#define SC_THREAD_FUNCTION(f)       void *(*f)(void *)
+
+extern RDPDR_DEVICE g_rdpdr_device[];
+
+typedef struct _MEM_HANDLE
+{
+	struct _MEM_HANDLE *prevHandle;
+	struct _MEM_HANDLE *nextHandle;
+	int dataSize;
+} MEM_HANDLE, *PMEM_HANDLE;
+
+typedef struct _SCARD_ATRMASK_L
+{
+	unsigned int cbAtr;
+	unsigned char rgbAtr[36];
+	unsigned char rgbMask[36];
+} SCARD_ATRMASK_L, *PSCARD_ATRMASK_L, *LPSCARD_ATRMASK_L;
+
+typedef struct _TSCNameMapRec
+{
+	char alias[128];
+	char name[128];
+	char vendor[128];
+} TSCNameMapRec, *PSCNameMapRec;
+
+typedef struct _TSCHCardRec
+{
+	DWORD hCard;
+	char *vendor;
+	struct _TSCHCardRec *next;
+	struct _TSCHCardRec *prev;
+} TSCHCardRec, *PSCHCardRec;
+
+typedef struct _TSCThreadData
+{
+	uint32 device;
+	uint32 id;
+	uint32 epoch;
+	RD_NTHANDLE handle;
+	uint32 request;
+	STREAM in;
+	STREAM out;
+	PMEM_HANDLE memHandle;
+	struct _TSCThreadData *next;
+} TSCThreadData, *PSCThreadData;
+
+typedef struct _TThreadListElement
+{
+	pthread_t thread;
+	pthread_mutex_t busy;
+	pthread_cond_t nodata;
+	PSCThreadData data;
+	struct _TThreadListElement *next;
+} TThreadListElement, *PThreadListElement;
Index: /trunk/src/VBox/RDP/client-1.8.3/seamless.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/seamless.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/seamless.c	(revision 55121)
@@ -0,0 +1,556 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Seamless Windows support
+   Copyright 2005-2008 Peter Astrand <astrand@cendio.se> for Cendio AB
+   Copyright 2007-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
+   Copyright 2013-2014 Henrik Andersson  <hean01@cendio.se> for Cendio AB   
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+#include <stdarg.h>
+#include <assert.h>
+
+#ifdef WITH_DEBUG_SEAMLESS
+#define DEBUG_SEAMLESS(args) printf args;
+#else
+#define DEBUG_SEAMLESS(args)
+#endif
+
+extern RD_BOOL g_seamless_rdp;
+static VCHANNEL *seamless_channel;
+static unsigned int seamless_serial;
+static char *seamless_rest = NULL;
+static char icon_buf[1024];
+
+static char *
+seamless_get_token(char **s)
+{
+	char *comma, *head;
+	head = *s;
+
+	if (!head)
+		return NULL;
+
+	comma = strchr(head, ',');
+	if (comma)
+	{
+		*comma = '\0';
+		*s = comma + 1;
+	}
+	else
+	{
+		*s = NULL;
+	}
+
+	return head;
+}
+
+
+static RD_BOOL
+seamless_process_line(const char *line, void *data)
+{
+	char *p, *l;
+	char *tok1, *tok2, *tok3, *tok4, *tok5, *tok6, *tok7, *tok8;
+	unsigned long id, flags;
+	char *endptr;
+
+	l = xstrdup(line);
+	p = l;
+
+	DEBUG_SEAMLESS(("seamlessrdp got:%s\n", p));
+
+	tok1 = seamless_get_token(&p);
+	tok2 = seamless_get_token(&p);
+	tok3 = seamless_get_token(&p);
+	tok4 = seamless_get_token(&p);
+	tok5 = seamless_get_token(&p);
+	tok6 = seamless_get_token(&p);
+	tok7 = seamless_get_token(&p);
+	tok8 = seamless_get_token(&p);
+
+	if (!strcmp("CREATE", tok1))
+	{
+		unsigned long group, parent;
+		if (!tok6)
+			return False;
+
+		id = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		group = strtoul(tok4, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		parent = strtoul(tok5, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		flags = strtoul(tok6, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_create_window(id, group, parent, flags);
+	}
+	else if (!strcmp("DESTROY", tok1))
+	{
+		if (!tok4)
+			return False;
+
+		id = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		flags = strtoul(tok4, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_destroy_window(id, flags);
+
+	}
+	else if (!strcmp("DESTROYGRP", tok1))
+	{
+		if (!tok4)
+			return False;
+
+		id = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		flags = strtoul(tok4, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_destroy_group(id, flags);
+	}
+	else if (!strcmp("SETICON", tok1))
+	{
+		int chunk, width, height, len;
+		char byte[3];
+
+		if (!tok8)
+			return False;
+
+		id = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		chunk = strtoul(tok4, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		width = strtoul(tok6, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		height = strtoul(tok7, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		byte[2] = '\0';
+		len = 0;
+		while (*tok8 != '\0')
+		{
+			byte[0] = *tok8;
+			tok8++;
+			if (*tok8 == '\0')
+				return False;
+			byte[1] = *tok8;
+			tok8++;
+
+			icon_buf[len] = strtol(byte, NULL, 16);
+			len++;
+		}
+
+		ui_seamless_seticon(id, tok5, width, height, chunk, icon_buf, len);
+	}
+	else if (!strcmp("DELICON", tok1))
+	{
+		int width, height;
+
+		if (!tok6)
+			return False;
+
+		id = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		width = strtoul(tok5, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		height = strtoul(tok6, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_delicon(id, tok4, width, height);
+	}
+	else if (!strcmp("POSITION", tok1))
+	{
+		int x, y, width, height;
+
+		if (!tok8)
+			return False;
+
+		id = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		x = strtol(tok4, &endptr, 0);
+		if (*endptr)
+			return False;
+		y = strtol(tok5, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		width = strtol(tok6, &endptr, 0);
+		if (*endptr)
+			return False;
+		height = strtol(tok7, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		flags = strtoul(tok8, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_move_window(id, x, y, width, height, flags);
+	}
+	else if (!strcmp("ZCHANGE", tok1))
+	{
+		unsigned long behind;
+
+		id = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		behind = strtoul(tok4, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		flags = strtoul(tok5, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_restack_window(id, behind, flags);
+	}
+	else if (!strcmp("TITLE", tok1))
+	{
+		if (!tok5)
+			return False;
+
+		id = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		flags = strtoul(tok5, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_settitle(id, tok4, flags);
+	}
+	else if (!strcmp("STATE", tok1))
+	{
+		unsigned int state;
+
+		if (!tok5)
+			return False;
+
+		id = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		state = strtoul(tok4, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		flags = strtoul(tok5, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_setstate(id, state, flags);
+	}
+	else if (!strcmp("DEBUG", tok1))
+	{
+		DEBUG_SEAMLESS(("SeamlessRDP:%s\n", line));
+	}
+	else if (!strcmp("SYNCBEGIN", tok1))
+	{
+		if (!tok3)
+			return False;
+
+		flags = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_syncbegin(flags);
+	}
+	else if (!strcmp("SYNCEND", tok1))
+	{
+		if (!tok3)
+			return False;
+
+		flags = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		/* do nothing, currently */
+	}
+	else if (!strcmp("HELLO", tok1))
+	{
+		if (!tok3)
+			return False;
+
+		flags = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_begin(! !(flags & SEAMLESSRDP_HELLO_HIDDEN));
+	}
+	else if (!strcmp("ACK", tok1))
+	{
+		unsigned int serial;
+
+		serial = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_ack(serial);
+	}
+	else if (!strcmp("HIDE", tok1))
+	{
+		if (!tok3)
+			return False;
+
+		flags = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_hide_desktop();
+	}
+	else if (!strcmp("UNHIDE", tok1))
+	{
+		if (!tok3)
+			return False;
+
+		flags = strtoul(tok3, &endptr, 0);
+		if (*endptr)
+			return False;
+
+		ui_seamless_unhide_desktop();
+	}
+
+
+	xfree(l);
+	return True;
+}
+
+
+static RD_BOOL
+seamless_line_handler(const char *line, void *data)
+{
+	if (!seamless_process_line(line, data))
+	{
+		warning("SeamlessRDP: Invalid request:%s\n", line);
+	}
+	return True;
+}
+
+
+static void
+seamless_process(STREAM s)
+{
+	unsigned int pkglen;
+	char *buf;
+
+	pkglen = s->end - s->p;
+	/* str_handle_lines requires null terminated strings */
+	buf = xmalloc(pkglen + 1);
+	STRNCPY(buf, (char *) s->p, pkglen + 1);
+#if 0
+	printf("seamless recv:\n");
+	hexdump(s->p, pkglen);
+#endif
+
+	str_handle_lines(buf, &seamless_rest, seamless_line_handler, NULL);
+
+	xfree(buf);
+}
+
+
+RD_BOOL
+seamless_init(void)
+{
+	if (!g_seamless_rdp)
+		return False;
+
+	seamless_serial = 0;
+
+	seamless_channel =
+		channel_register("seamrdp", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
+				 seamless_process);
+	return (seamless_channel != NULL);
+}
+
+void
+seamless_reset_state(void)
+{
+	if (seamless_rest != NULL)
+	{
+		xfree(seamless_rest);
+		seamless_rest = NULL;
+	}
+}
+
+static unsigned int
+seamless_send(const char *command, const char *format, ...)
+{
+	STREAM s;
+	size_t len;
+	va_list argp;
+	char *escaped, buf[1025];
+
+	len = snprintf(buf, sizeof(buf) - 1, "%s,%u,", command, seamless_serial);
+
+	assert(len < (sizeof(buf) - 1));
+
+	va_start(argp, format);
+	len += vsnprintf(buf + len, sizeof(buf) - len - 1, format, argp);
+	va_end(argp);
+
+	assert(len < (sizeof(buf) - 1));
+
+	escaped = utils_string_escape(buf);
+	len = snprintf(buf, sizeof(buf), "%s", escaped);
+	free(escaped);
+	assert(len < (sizeof(buf) - 1));
+
+	buf[len] = '\n';
+	buf[len + 1] = '\0';
+
+	len++;
+
+	s = channel_init(seamless_channel, len);
+	out_uint8p(s, buf, len) s_mark_end(s);
+
+	DEBUG_SEAMLESS(("seamlessrdp sending:%s", buf));
+
+#if 0
+	printf("seamless send:\n");
+	hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
+#endif
+
+	channel_send(s, seamless_channel);
+
+	return seamless_serial++;
+}
+
+
+unsigned int
+seamless_send_sync()
+{
+	if (!g_seamless_rdp)
+		return (unsigned int) -1;
+
+	return seamless_send("SYNC", "");
+}
+
+
+unsigned int
+seamless_send_state(unsigned long id, unsigned int state, unsigned long flags)
+{
+	if (!g_seamless_rdp)
+		return (unsigned int) -1;
+
+	return seamless_send("STATE", "0x%08lx,0x%x,0x%lx", id, state, flags);
+}
+
+
+unsigned int
+seamless_send_position(unsigned long id, int x, int y, int width, int height, unsigned long flags)
+{
+	return seamless_send("POSITION", "0x%08lx,%d,%d,%d,%d,0x%lx", id, x, y, width, height,
+			     flags);
+}
+
+
+/* Update select timeout */
+void
+seamless_select_timeout(struct timeval *tv)
+{
+	struct timeval ourtimeout = { 0, SEAMLESSRDP_POSITION_TIMER };
+
+	if (g_seamless_rdp)
+	{
+		if (timercmp(&ourtimeout, tv, <))
+		{
+			tv->tv_sec = ourtimeout.tv_sec;
+			tv->tv_usec = ourtimeout.tv_usec;
+		}
+	}
+}
+
+
+unsigned int
+seamless_send_zchange(unsigned long id, unsigned long below, unsigned long flags)
+{
+	if (!g_seamless_rdp)
+		return (unsigned int) -1;
+
+	return seamless_send("ZCHANGE", "0x%08lx,0x%08lx,0x%lx", id, below, flags);
+}
+
+
+
+unsigned int
+seamless_send_focus(unsigned long id, unsigned long flags)
+{
+	if (!g_seamless_rdp)
+		return (unsigned int) -1;
+
+	return seamless_send("FOCUS", "0x%08lx,0x%lx", id, flags);
+}
+
+/* Send client-to-server message to destroy process on the server. */
+unsigned int
+seamless_send_destroy(unsigned long id)
+{
+	return seamless_send("DESTROY", "0x%08lx", id);
+}
+
+unsigned int
+seamless_send_spawn(char *cmdline)
+{
+	unsigned int res;
+	if (!g_seamless_rdp)
+		return (unsigned int) -1;
+
+	res = seamless_send("SPAWN", cmdline);
+
+	return res;
+}
+
+unsigned int
+seamless_send_persistent(RD_BOOL enable)
+{
+	unsigned int res;
+	if (!g_seamless_rdp)
+		return (unsigned int) -1;
+	printf("%s persistent seamless mode.\n", enable?"Enable":"Disable");
+	res = seamless_send("PERSISTENT", "%d", enable);
+	
+	return res;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/seamless.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/seamless.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/seamless.h	(revision 55121)
@@ -0,0 +1,18 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   Seamless Windows support
+   Copyright 2005-2008 Peter Astrand <astrand@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
Index: /trunk/src/VBox/RDP/client-1.8.3/secure.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/secure.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/secure.c	(revision 55121)
@@ -0,0 +1,936 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - RDP encryption and licensing
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+#include "ssl.h"
+
+extern char g_hostname[16];
+extern int g_width;
+extern int g_height;
+extern unsigned int g_keylayout;
+extern int g_keyboard_type;
+extern int g_keyboard_subtype;
+extern int g_keyboard_functionkeys;
+extern RD_BOOL g_encryption;
+extern RD_BOOL g_licence_issued;
+extern RD_BOOL g_licence_error_result;
+extern RDP_VERSION g_rdp_version;
+extern RD_BOOL g_console_session;
+extern uint32 g_redirect_session_id;
+extern int g_server_depth;
+extern VCHANNEL g_channels[];
+extern unsigned int g_num_channels;
+extern uint8 g_client_random[SEC_RANDOM_SIZE];
+
+static int g_rc4_key_len;
+static RDSSL_RC4 g_rc4_decrypt_key;
+static RDSSL_RC4 g_rc4_encrypt_key;
+static uint32 g_server_public_key_len;
+
+static uint8 g_sec_sign_key[16];
+static uint8 g_sec_decrypt_key[16];
+static uint8 g_sec_encrypt_key[16];
+static uint8 g_sec_decrypt_update_key[16];
+static uint8 g_sec_encrypt_update_key[16];
+static uint8 g_sec_crypted_random[SEC_MAX_MODULUS_SIZE];
+
+uint16 g_server_rdp_version = 0;
+
+/* These values must be available to reset state - Session Directory */
+static int g_sec_encrypt_use_count = 0;
+static int g_sec_decrypt_use_count = 0;
+
+/*
+ * I believe this is based on SSLv3 with the following differences:
+ *  MAC algorithm (5.2.3.1) uses only 32-bit length in place of seq_num/type/length fields
+ *  MAC algorithm uses SHA1 and MD5 for the two hash functions instead of one or other
+ *  key_block algorithm (6.2.2) uses 'X', 'YY', 'ZZZ' instead of 'A', 'BB', 'CCC'
+ *  key_block partitioning is different (16 bytes each: MAC secret, decrypt key, encrypt key)
+ *  encryption/decryption keys updated every 4096 packets
+ * See http://wp.netscape.com/eng/ssl3/draft302.txt
+ */
+
+/*
+ * 48-byte transformation used to generate master secret (6.1) and key material (6.2.2).
+ * Both SHA1 and MD5 algorithms are used.
+ */
+void
+sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt)
+{
+	uint8 shasig[20];
+	uint8 pad[4];
+	RDSSL_SHA1 sha1;
+	RDSSL_MD5 md5;
+	int i;
+
+	for (i = 0; i < 3; i++)
+	{
+		memset(pad, salt + i, i + 1);
+
+		rdssl_sha1_init(&sha1);
+		rdssl_sha1_update(&sha1, pad, i + 1);
+		rdssl_sha1_update(&sha1, in, 48);
+		rdssl_sha1_update(&sha1, salt1, 32);
+		rdssl_sha1_update(&sha1, salt2, 32);
+		rdssl_sha1_final(&sha1, shasig);
+
+		rdssl_md5_init(&md5);
+		rdssl_md5_update(&md5, in, 48);
+		rdssl_md5_update(&md5, shasig, 20);
+		rdssl_md5_final(&md5, &out[i * 16]);
+	}
+}
+
+/*
+ * 16-byte transformation used to generate export keys (6.2.2).
+ */
+void
+sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2)
+{
+	RDSSL_MD5 md5;
+
+	rdssl_md5_init(&md5);
+	rdssl_md5_update(&md5, in, 16);
+	rdssl_md5_update(&md5, salt1, 32);
+	rdssl_md5_update(&md5, salt2, 32);
+	rdssl_md5_final(&md5, out);
+}
+
+/*
+ * 16-byte sha1 hash
+ */
+void
+sec_hash_sha1_16(uint8 * out, uint8 * in, uint8 * salt1)
+{
+	RDSSL_SHA1 sha1;
+	rdssl_sha1_init(&sha1);
+	rdssl_sha1_update(&sha1, in, 16);
+	rdssl_sha1_update(&sha1, salt1, 16);
+	rdssl_sha1_final(&sha1, out);
+}
+
+/* create string from hash */
+void
+sec_hash_to_string(char *out, int out_size, uint8 * in, int in_size)
+{
+	int k;
+	memset(out, 0, out_size);
+	for (k = 0; k < in_size; k++, out += 2)
+	{
+		sprintf(out, "%.2x", in[k]);
+	}
+}
+
+/* Reduce key entropy from 64 to 40 bits */
+static void
+sec_make_40bit(uint8 * key)
+{
+	key[0] = 0xd1;
+	key[1] = 0x26;
+	key[2] = 0x9e;
+}
+
+/* Generate encryption keys given client and server randoms */
+static void
+sec_generate_keys(uint8 * client_random, uint8 * server_random, int rc4_key_size)
+{
+	uint8 pre_master_secret[48];
+	uint8 master_secret[48];
+	uint8 key_block[48];
+
+	/* Construct pre-master secret */
+	memcpy(pre_master_secret, client_random, 24);
+	memcpy(pre_master_secret + 24, server_random, 24);
+
+	/* Generate master secret and then key material */
+	sec_hash_48(master_secret, pre_master_secret, client_random, server_random, 'A');
+	sec_hash_48(key_block, master_secret, client_random, server_random, 'X');
+
+	/* First 16 bytes of key material is MAC secret */
+	memcpy(g_sec_sign_key, key_block, 16);
+
+	/* Generate export keys from next two blocks of 16 bytes */
+	sec_hash_16(g_sec_decrypt_key, &key_block[16], client_random, server_random);
+	sec_hash_16(g_sec_encrypt_key, &key_block[32], client_random, server_random);
+
+	if (rc4_key_size == 1)
+	{
+		DEBUG(("40-bit encryption enabled\n"));
+		sec_make_40bit(g_sec_sign_key);
+		sec_make_40bit(g_sec_decrypt_key);
+		sec_make_40bit(g_sec_encrypt_key);
+		g_rc4_key_len = 8;
+	}
+	else
+	{
+		DEBUG(("rc_4_key_size == %d, 128-bit encryption enabled\n", rc4_key_size));
+		g_rc4_key_len = 16;
+	}
+
+	/* Save initial RC4 keys as update keys */
+	memcpy(g_sec_decrypt_update_key, g_sec_decrypt_key, 16);
+	memcpy(g_sec_encrypt_update_key, g_sec_encrypt_key, 16);
+
+	/* Initialise RC4 state arrays */
+	rdssl_rc4_set_key(&g_rc4_decrypt_key, g_sec_decrypt_key, g_rc4_key_len);
+	rdssl_rc4_set_key(&g_rc4_encrypt_key, g_sec_encrypt_key, g_rc4_key_len);
+}
+
+static uint8 pad_54[40] = {
+	54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+	54, 54, 54,
+	54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+	54, 54, 54
+};
+
+static uint8 pad_92[48] = {
+	92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+	92, 92, 92, 92, 92, 92, 92,
+	92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+	92, 92, 92, 92, 92, 92, 92
+};
+
+/* Output a uint32 into a buffer (little-endian) */
+void
+buf_out_uint32(uint8 * buffer, uint32 value)
+{
+	buffer[0] = (value) & 0xff;
+	buffer[1] = (value >> 8) & 0xff;
+	buffer[2] = (value >> 16) & 0xff;
+	buffer[3] = (value >> 24) & 0xff;
+}
+
+/* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */
+void
+sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, int datalen)
+{
+	uint8 shasig[20];
+	uint8 md5sig[16];
+	uint8 lenhdr[4];
+	RDSSL_SHA1 sha1;
+	RDSSL_MD5 md5;
+
+	buf_out_uint32(lenhdr, datalen);
+
+	rdssl_sha1_init(&sha1);
+	rdssl_sha1_update(&sha1, session_key, keylen);
+	rdssl_sha1_update(&sha1, pad_54, 40);
+	rdssl_sha1_update(&sha1, lenhdr, 4);
+	rdssl_sha1_update(&sha1, data, datalen);
+	rdssl_sha1_final(&sha1, shasig);
+
+	rdssl_md5_init(&md5);
+	rdssl_md5_update(&md5, session_key, keylen);
+	rdssl_md5_update(&md5, pad_92, 48);
+	rdssl_md5_update(&md5, shasig, 20);
+	rdssl_md5_final(&md5, md5sig);
+
+	memcpy(signature, md5sig, siglen);
+}
+
+/* Update an encryption key */
+static void
+sec_update(uint8 * key, uint8 * update_key)
+{
+	uint8 shasig[20];
+	RDSSL_SHA1 sha1;
+	RDSSL_MD5 md5;
+	RDSSL_RC4 update;
+
+	rdssl_sha1_init(&sha1);
+	rdssl_sha1_update(&sha1, update_key, g_rc4_key_len);
+	rdssl_sha1_update(&sha1, pad_54, 40);
+	rdssl_sha1_update(&sha1, key, g_rc4_key_len);
+	rdssl_sha1_final(&sha1, shasig);
+
+	rdssl_md5_init(&md5);
+	rdssl_md5_update(&md5, update_key, g_rc4_key_len);
+	rdssl_md5_update(&md5, pad_92, 48);
+	rdssl_md5_update(&md5, shasig, 20);
+	rdssl_md5_final(&md5, key);
+
+	rdssl_rc4_set_key(&update, key, g_rc4_key_len);
+	rdssl_rc4_crypt(&update, key, key, g_rc4_key_len);
+
+	if (g_rc4_key_len == 8)
+		sec_make_40bit(key);
+}
+
+/* Encrypt data using RC4 */
+static void
+sec_encrypt(uint8 * data, int length)
+{
+	if (g_sec_encrypt_use_count == 4096)
+	{
+		sec_update(g_sec_encrypt_key, g_sec_encrypt_update_key);
+		rdssl_rc4_set_key(&g_rc4_encrypt_key, g_sec_encrypt_key, g_rc4_key_len);
+		g_sec_encrypt_use_count = 0;
+	}
+
+	rdssl_rc4_crypt(&g_rc4_encrypt_key, data, data, length);
+	g_sec_encrypt_use_count++;
+}
+
+/* Decrypt data using RC4 */
+void
+sec_decrypt(uint8 * data, int length)
+{
+	if (g_sec_decrypt_use_count == 4096)
+	{
+		sec_update(g_sec_decrypt_key, g_sec_decrypt_update_key);
+		rdssl_rc4_set_key(&g_rc4_decrypt_key, g_sec_decrypt_key, g_rc4_key_len);
+		g_sec_decrypt_use_count = 0;
+	}
+
+	rdssl_rc4_crypt(&g_rc4_decrypt_key, data, data, length);
+	g_sec_decrypt_use_count++;
+}
+
+/* Perform an RSA public key encryption operation */
+static void
+sec_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
+		uint8 * exponent)
+{
+	rdssl_rsa_encrypt(out, in, len, modulus_size, modulus, exponent);
+}
+
+/* Initialise secure transport packet */
+STREAM
+sec_init(uint32 flags, int maxlen)
+{
+	int hdrlen;
+	STREAM s;
+
+	if (!g_licence_issued && !g_licence_error_result)
+		hdrlen = (flags & SEC_ENCRYPT) ? 12 : 4;
+	else
+		hdrlen = (flags & SEC_ENCRYPT) ? 12 : 0;
+	s = mcs_init(maxlen + hdrlen);
+	s_push_layer(s, sec_hdr, hdrlen);
+
+	return s;
+}
+
+/* Transmit secure transport packet over specified channel */
+void
+sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
+{
+	int datalen;
+
+#ifdef WITH_SCARD
+	scard_lock(SCARD_LOCK_SEC);
+#endif
+
+	s_pop_layer(s, sec_hdr);
+	if ((!g_licence_issued && !g_licence_error_result) || (flags & SEC_ENCRYPT))
+		out_uint32_le(s, flags);
+
+	if (flags & SEC_ENCRYPT)
+	{
+		flags &= ~SEC_ENCRYPT;
+		datalen = s->end - s->p - 8;
+
+#if WITH_DEBUG
+		DEBUG(("Sending encrypted packet:\n"));
+		hexdump(s->p + 8, datalen);
+#endif
+
+		sec_sign(s->p, 8, g_sec_sign_key, g_rc4_key_len, s->p + 8, datalen);
+		sec_encrypt(s->p + 8, datalen);
+	}
+
+	mcs_send_to_channel(s, channel);
+
+#ifdef WITH_SCARD
+	scard_unlock(SCARD_LOCK_SEC);
+#endif
+}
+
+/* Transmit secure transport packet */
+
+void
+sec_send(STREAM s, uint32 flags)
+{
+	sec_send_to_channel(s, flags, MCS_GLOBAL_CHANNEL);
+}
+
+
+/* Transfer the client random to the server */
+static void
+sec_establish_key(void)
+{
+	uint32 length = g_server_public_key_len + SEC_PADDING_SIZE;
+	uint32 flags = SEC_CLIENT_RANDOM;
+	STREAM s;
+
+	s = sec_init(flags, length + 4);
+
+	out_uint32_le(s, length);
+	out_uint8p(s, g_sec_crypted_random, g_server_public_key_len);
+	out_uint8s(s, SEC_PADDING_SIZE);
+
+	s_mark_end(s);
+	sec_send(s, flags);
+}
+
+/* Output connect initial data blob */
+static void
+sec_out_mcs_data(STREAM s, uint32 selected_protocol)
+{
+	int hostlen = 2 * strlen(g_hostname);
+	int length = 162 + 76 + 12 + 4;
+	unsigned int i;
+
+	if (g_num_channels > 0)
+		length += g_num_channels * 12 + 8;
+
+	if (hostlen > 30)
+		hostlen = 30;
+
+	/* Generic Conference Control (T.124) ConferenceCreateRequest */
+	out_uint16_be(s, 5);
+	out_uint16_be(s, 0x14);
+	out_uint8(s, 0x7c);
+	out_uint16_be(s, 1);
+
+	out_uint16_be(s, (length | 0x8000));	/* remaining length */
+
+	out_uint16_be(s, 8);	/* length? */
+	out_uint16_be(s, 16);
+	out_uint8(s, 0);
+	out_uint16_le(s, 0xc001);
+	out_uint8(s, 0);
+
+	out_uint32_le(s, 0x61637544);	/* OEM ID: "Duca", as in Ducati. */
+	out_uint16_be(s, ((length - 14) | 0x8000));	/* remaining length */
+
+	/* Client information */
+	out_uint16_le(s, SEC_TAG_CLI_INFO);
+	out_uint16_le(s, 216);	/* length */
+	out_uint16_le(s, (g_rdp_version >= RDP_V5) ? 4 : 1);	/* RDP version. 1 == RDP4, 4 >= RDP5 to RDP8 */
+	out_uint16_le(s, 8);
+	out_uint16_le(s, g_width);
+	out_uint16_le(s, g_height);
+	out_uint16_le(s, 0xca01);
+	out_uint16_le(s, 0xaa03);
+	out_uint32_le(s, g_keylayout);
+	out_uint32_le(s, 2600);	/* Client build. We are now 2600 compatible :-) */
+
+	/* Unicode name of client, padded to 32 bytes */
+	rdp_out_unistr(s, g_hostname, hostlen);
+	out_uint8s(s, 30 - hostlen);
+
+	/* See
+	   http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceddk40/html/cxtsksupportingremotedesktopprotocol.asp */
+	out_uint32_le(s, g_keyboard_type);
+	out_uint32_le(s, g_keyboard_subtype);
+	out_uint32_le(s, g_keyboard_functionkeys);
+	out_uint8s(s, 64);	/* reserved? 4 + 12 doublewords */
+	out_uint16_le(s, 0xca01);	/* colour depth? */
+	out_uint16_le(s, 1);
+
+	out_uint32(s, 0);
+	out_uint8(s, g_server_depth);
+	out_uint16_le(s, 0x0700);
+	out_uint8(s, 0);
+	out_uint32_le(s, 1);
+	out_uint8s(s, 64);
+	out_uint32_le(s, selected_protocol);	/* End of client info */
+
+	/* Write a Client Cluster Data (TS_UD_CS_CLUSTER) */
+	uint32 cluster_flags = 0;
+	out_uint16_le(s, SEC_TAG_CLI_CLUSTER);	/* header.type */
+	out_uint16_le(s, 12);	/* length */
+
+	cluster_flags |= SEC_CC_REDIRECTION_SUPPORTED;
+	cluster_flags |= (SEC_CC_REDIRECT_VERSION_3 << 2);
+
+	if (g_console_session || g_redirect_session_id != 0)
+		cluster_flags |= SEC_CC_REDIRECT_SESSIONID_FIELD_VALID;
+
+	out_uint32_le(s, cluster_flags);
+	out_uint32(s, g_redirect_session_id);
+
+	/* Client encryption settings */
+	out_uint16_le(s, SEC_TAG_CLI_CRYPT);
+	out_uint16_le(s, 12);	/* length */
+	out_uint32_le(s, g_encryption ? 0x3 : 0);	/* encryption supported, 128-bit supported */
+	out_uint32(s, 0);	/* Unknown */
+
+	DEBUG_RDP5(("g_num_channels is %d\n", g_num_channels));
+	if (g_num_channels > 0)
+	{
+		out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
+		out_uint16_le(s, g_num_channels * 12 + 8);	/* length */
+		out_uint32_le(s, g_num_channels);	/* number of virtual channels */
+		for (i = 0; i < g_num_channels; i++)
+		{
+			DEBUG_RDP5(("Requesting channel %s\n", g_channels[i].name));
+			out_uint8a(s, g_channels[i].name, 8);
+			out_uint32_be(s, g_channels[i].flags);
+		}
+	}
+
+	s_mark_end(s);
+}
+
+/* Parse a public key structure */
+static RD_BOOL
+sec_parse_public_key(STREAM s, uint8 * modulus, uint8 * exponent)
+{
+	uint32 magic, modulus_len;
+
+	in_uint32_le(s, magic);
+	if (magic != SEC_RSA_MAGIC)
+	{
+		error("RSA magic 0x%x\n", magic);
+		return False;
+	}
+
+	in_uint32_le(s, modulus_len);
+	modulus_len -= SEC_PADDING_SIZE;
+	if ((modulus_len < SEC_MODULUS_SIZE) || (modulus_len > SEC_MAX_MODULUS_SIZE))
+	{
+		error("Bad server public key size (%u bits)\n", modulus_len * 8);
+		return False;
+	}
+
+	in_uint8s(s, 8);	/* modulus_bits, unknown */
+	in_uint8a(s, exponent, SEC_EXPONENT_SIZE);
+	in_uint8a(s, modulus, modulus_len);
+	in_uint8s(s, SEC_PADDING_SIZE);
+	g_server_public_key_len = modulus_len;
+
+	return s_check(s);
+}
+
+/* Parse a public signature structure */
+static RD_BOOL
+sec_parse_public_sig(STREAM s, uint32 len, uint8 * modulus, uint8 * exponent)
+{
+	uint8 signature[SEC_MAX_MODULUS_SIZE];
+	uint32 sig_len;
+
+	if (len != 72)
+	{
+		return True;
+	}
+	memset(signature, 0, sizeof(signature));
+	sig_len = len - 8;
+	in_uint8a(s, signature, sig_len);
+	return rdssl_sig_ok(exponent, SEC_EXPONENT_SIZE, modulus, g_server_public_key_len,
+			    signature, sig_len);
+}
+
+/* Parse a crypto information structure */
+static RD_BOOL
+sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
+		     uint8 ** server_random, uint8 * modulus, uint8 * exponent)
+{
+	uint32 crypt_level, random_len, rsa_info_len;
+	uint32 cacert_len, cert_len, flags;
+	RDSSL_CERT *cacert, *server_cert;
+	RDSSL_RKEY *server_public_key;
+	uint16 tag, length;
+	uint8 *next_tag, *end;
+
+	in_uint32_le(s, *rc4_key_size);	/* 1 = 40-bit, 2 = 128-bit */
+	in_uint32_le(s, crypt_level);	/* 1 = low, 2 = medium, 3 = high */
+	if (crypt_level == 0)
+	{
+		/* no encryption */
+		return False;
+	}
+
+	in_uint32_le(s, random_len);
+	in_uint32_le(s, rsa_info_len);
+
+	if (random_len != SEC_RANDOM_SIZE)
+	{
+		error("random len %d, expected %d\n", random_len, SEC_RANDOM_SIZE);
+		return False;
+	}
+
+	in_uint8p(s, *server_random, random_len);
+
+	/* RSA info */
+	end = s->p + rsa_info_len;
+	if (end > s->end)
+		return False;
+
+	in_uint32_le(s, flags);	/* 1 = RDP4-style, 0x80000002 = X.509 */
+	if (flags & 1)
+	{
+		DEBUG_RDP5(("We're going for the RDP4-style encryption\n"));
+		in_uint8s(s, 8);	/* unknown */
+
+		while (s->p < end)
+		{
+			in_uint16_le(s, tag);
+			in_uint16_le(s, length);
+
+			next_tag = s->p + length;
+
+			switch (tag)
+			{
+				case SEC_TAG_PUBKEY:
+					if (!sec_parse_public_key(s, modulus, exponent))
+						return False;
+					DEBUG_RDP5(("Got Public key, RDP4-style\n"));
+
+					break;
+
+				case SEC_TAG_KEYSIG:
+					if (!sec_parse_public_sig(s, length, modulus, exponent))
+						return False;
+					break;
+
+				default:
+					unimpl("crypt tag 0x%x\n", tag);
+			}
+
+			s->p = next_tag;
+		}
+	}
+	else
+	{
+		uint32 certcount;
+
+		DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
+		in_uint32_le(s, certcount);	/* Number of certificates */
+		if (certcount < 2)
+		{
+			error("Server didn't send enough X509 certificates\n");
+			return False;
+		}
+		for (; certcount > 2; certcount--)
+		{		/* ignore all the certificates between the root and the signing CA */
+			uint32 ignorelen;
+			RDSSL_CERT *ignorecert;
+
+			DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
+			in_uint32_le(s, ignorelen);
+			DEBUG_RDP5(("Ignored Certificate length is %d\n", ignorelen));
+			ignorecert = rdssl_cert_read(s->p, ignorelen);
+			in_uint8s(s, ignorelen);
+			if (ignorecert == NULL)
+			{	/* XXX: error out? */
+				DEBUG_RDP5(("got a bad cert: this will probably screw up the rest of the communication\n"));
+			}
+
+#ifdef WITH_DEBUG_RDP5
+			DEBUG_RDP5(("cert #%d (ignored):\n", certcount));
+			rdssl_cert_print_fp(stdout, ignorecert);
+#endif
+		}
+		/* Do da funky X.509 stuffy
+
+		   "How did I find out about this?  I looked up and saw a
+		   bright light and when I came to I had a scar on my forehead
+		   and knew about X.500"
+		   - Peter Gutman in a early version of 
+		   http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
+		 */
+		in_uint32_le(s, cacert_len);
+		DEBUG_RDP5(("CA Certificate length is %d\n", cacert_len));
+		cacert = rdssl_cert_read(s->p, cacert_len);
+		in_uint8s(s, cacert_len);
+		if (NULL == cacert)
+		{
+			error("Couldn't load CA Certificate from server\n");
+			return False;
+		}
+		in_uint32_le(s, cert_len);
+		DEBUG_RDP5(("Certificate length is %d\n", cert_len));
+		server_cert = rdssl_cert_read(s->p, cert_len);
+		in_uint8s(s, cert_len);
+		if (NULL == server_cert)
+		{
+			rdssl_cert_free(cacert);
+			error("Couldn't load Certificate from server\n");
+			return False;
+		}
+		if (!rdssl_certs_ok(server_cert, cacert))
+		{
+			rdssl_cert_free(server_cert);
+			rdssl_cert_free(cacert);
+			error("Security error CA Certificate invalid\n");
+			return False;
+		}
+		rdssl_cert_free(cacert);
+		in_uint8s(s, 16);	/* Padding */
+		server_public_key = rdssl_cert_to_rkey(server_cert, &g_server_public_key_len);
+		if (NULL == server_public_key)
+		{
+			DEBUG_RDP5(("Didn't parse X509 correctly\n"));
+			rdssl_cert_free(server_cert);
+			return False;
+		}
+		rdssl_cert_free(server_cert);
+		if ((g_server_public_key_len < SEC_MODULUS_SIZE) ||
+		    (g_server_public_key_len > SEC_MAX_MODULUS_SIZE))
+		{
+			error("Bad server public key size (%u bits)\n",
+			      g_server_public_key_len * 8);
+			rdssl_rkey_free(server_public_key);
+			return False;
+		}
+		if (rdssl_rkey_get_exp_mod(server_public_key, exponent, SEC_EXPONENT_SIZE,
+					   modulus, SEC_MAX_MODULUS_SIZE) != 0)
+		{
+			error("Problem extracting RSA exponent, modulus");
+			rdssl_rkey_free(server_public_key);
+			return False;
+		}
+		rdssl_rkey_free(server_public_key);
+		return True;	/* There's some garbage here we don't care about */
+	}
+	return s_check_end(s);
+}
+
+/* Process crypto information blob */
+static void
+sec_process_crypt_info(STREAM s)
+{
+	uint8 *server_random = NULL;
+	uint8 modulus[SEC_MAX_MODULUS_SIZE];
+	uint8 exponent[SEC_EXPONENT_SIZE];
+	uint32 rc4_key_size;
+
+	memset(modulus, 0, sizeof(modulus));
+	memset(exponent, 0, sizeof(exponent));
+	if (!sec_parse_crypt_info(s, &rc4_key_size, &server_random, modulus, exponent))
+	{
+		DEBUG(("Failed to parse crypt info\n"));
+		return;
+	}
+	DEBUG(("Generating client random\n"));
+	generate_random(g_client_random);
+	sec_rsa_encrypt(g_sec_crypted_random, g_client_random, SEC_RANDOM_SIZE,
+			g_server_public_key_len, modulus, exponent);
+	sec_generate_keys(g_client_random, server_random, rc4_key_size);
+}
+
+
+/* Process SRV_INFO, find RDP version supported by server */
+static void
+sec_process_srv_info(STREAM s)
+{
+	in_uint16_le(s, g_server_rdp_version);
+	DEBUG_RDP5(("Server RDP version is %d\n", g_server_rdp_version));
+	if (1 == g_server_rdp_version)
+	{
+		g_rdp_version = RDP_V4;
+		g_server_depth = 8;
+	}
+}
+
+
+/* Process connect response data blob */
+void
+sec_process_mcs_data(STREAM s)
+{
+	uint16 tag, length;
+	uint8 *next_tag;
+	uint8 len;
+
+	in_uint8s(s, 21);	/* header (T.124 ConferenceCreateResponse) */
+	in_uint8(s, len);
+	if (len & 0x80)
+		in_uint8(s, len);
+
+	while (s->p < s->end)
+	{
+		in_uint16_le(s, tag);
+		in_uint16_le(s, length);
+
+		if (length <= 4)
+			return;
+
+		next_tag = s->p + length - 4;
+
+		switch (tag)
+		{
+			case SEC_TAG_SRV_INFO:
+				sec_process_srv_info(s);
+				break;
+
+			case SEC_TAG_SRV_CRYPT:
+				sec_process_crypt_info(s);
+				break;
+
+			case SEC_TAG_SRV_CHANNELS:
+				/* FIXME: We should parse this information and
+				   use it to map RDP5 channels to MCS 
+				   channels */
+				break;
+
+			default:
+				unimpl("response tag 0x%x\n", tag);
+		}
+
+		s->p = next_tag;
+	}
+}
+
+/* Receive secure transport packet */
+STREAM
+sec_recv(uint8 * rdpver)
+{
+	uint32 sec_flags;
+	uint16 channel;
+	STREAM s;
+
+	while ((s = mcs_recv(&channel, rdpver)) != NULL)
+	{
+		if (rdpver != NULL)
+		{
+			if (*rdpver != 3)
+			{
+				if (*rdpver & 0x80)
+				{
+					in_uint8s(s, 8);	/* signature */
+					sec_decrypt(s->p, s->end - s->p);
+				}
+				return s;
+			}
+		}
+		if (g_encryption || (!g_licence_issued && !g_licence_error_result))
+		{
+			in_uint32_le(s, sec_flags);
+
+			if (g_encryption)
+			{
+				if (sec_flags & SEC_ENCRYPT)
+				{
+					in_uint8s(s, 8);	/* signature */
+					sec_decrypt(s->p, s->end - s->p);
+				}
+
+				if (sec_flags & SEC_LICENCE_NEG)
+				{
+					licence_process(s);
+					continue;
+				}
+
+				if (sec_flags & 0x0400)	/* SEC_REDIRECT_ENCRYPT */
+				{
+					uint8 swapbyte;
+
+					in_uint8s(s, 8);	/* signature */
+					sec_decrypt(s->p, s->end - s->p);
+
+					/* Check for a redirect packet, starts with 00 04 */
+					if (s->p[0] == 0 && s->p[1] == 4)
+					{
+						/* for some reason the PDU and the length seem to be swapped.
+						   This isn't good, but we're going to do a byte for byte
+						   swap.  So the first foure value appear as: 00 04 XX YY,
+						   where XX YY is the little endian length. We're going to
+						   use 04 00 as the PDU type, so after our swap this will look
+						   like: XX YY 04 00 */
+						swapbyte = s->p[0];
+						s->p[0] = s->p[2];
+						s->p[2] = swapbyte;
+
+						swapbyte = s->p[1];
+						s->p[1] = s->p[3];
+						s->p[3] = swapbyte;
+
+						swapbyte = s->p[2];
+						s->p[2] = s->p[3];
+						s->p[3] = swapbyte;
+					}
+#ifdef WITH_DEBUG
+					/* warning!  this debug statement will show passwords in the clear! */
+					hexdump(s->p, s->end - s->p);
+#endif
+				}
+			}
+			else
+			{
+				if ((sec_flags & 0xffff) == SEC_LICENCE_NEG)
+				{
+					licence_process(s);
+					continue;
+				}
+				s->p -= 4;
+			}
+		}
+
+		if (channel != MCS_GLOBAL_CHANNEL)
+		{
+			channel_process(s, channel);
+			if (rdpver != NULL)
+				*rdpver = 0xff;
+			return s;
+		}
+
+		return s;
+	}
+
+	return NULL;
+}
+
+/* Establish a secure connection */
+RD_BOOL
+sec_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect)
+{
+	uint32 selected_proto;
+	struct stream mcs_data;
+
+	/* Start a MCS connect sequence */
+	if (!mcs_connect_start(server, username, domain, password, reconnect, &selected_proto))
+		return False;
+
+	/* We exchange some RDP data during the MCS-Connect */
+	mcs_data.size = 512;
+	mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
+	sec_out_mcs_data(&mcs_data, selected_proto);
+
+	/* finialize the MCS connect sequence */
+	if (!mcs_connect_finalize(&mcs_data))
+		return False;
+
+	/* sec_process_mcs_data(&mcs_data); */
+	if (g_encryption)
+		sec_establish_key();
+	xfree(mcs_data.data);
+	return True;
+}
+
+/* Disconnect a connection */
+void
+sec_disconnect(void)
+{
+	mcs_disconnect();
+}
+
+/* reset the state of the sec layer */
+void
+sec_reset_state(void)
+{
+	g_server_rdp_version = 0;
+	g_sec_encrypt_use_count = 0;
+	g_sec_decrypt_use_count = 0;
+	g_licence_issued = 0;
+	g_licence_error_result = 0;
+	mcs_reset_state();
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/serial.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/serial.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/serial.c	(revision 55121)
@@ -0,0 +1,1074 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <strings.h>
+#include <sys/ioctl.h>
+
+#ifdef HAVE_SYS_MODEM_H
+#include <sys/modem.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+#ifdef HAVE_SYS_STRTIO_H
+#include <sys/strtio.h>
+#endif
+
+#include "rdesktop.h"
+
+#ifdef WITH_DEBUG_SERIAL
+#define DEBUG_SERIAL(args) printf args;
+#else
+#define DEBUG_SERIAL(args)
+#endif
+
+#define FILE_DEVICE_SERIAL_PORT		0x1b
+
+#define SERIAL_SET_BAUD_RATE		1
+#define SERIAL_SET_QUEUE_SIZE		2
+#define SERIAL_SET_LINE_CONTROL		3
+#define SERIAL_SET_BREAK_ON		4
+#define SERIAL_SET_BREAK_OFF		5
+#define SERIAL_IMMEDIATE_CHAR		6
+#define SERIAL_SET_TIMEOUTS		7
+#define SERIAL_GET_TIMEOUTS		8
+#define SERIAL_SET_DTR			9
+#define SERIAL_CLR_DTR			10
+#define SERIAL_RESET_DEVICE		11
+#define SERIAL_SET_RTS			12
+#define SERIAL_CLR_RTS			13
+#define SERIAL_SET_XOFF			14
+#define SERIAL_SET_XON			15
+#define SERIAL_GET_WAIT_MASK		16
+#define SERIAL_SET_WAIT_MASK		17
+#define SERIAL_WAIT_ON_MASK		18
+#define SERIAL_PURGE			19
+#define SERIAL_GET_BAUD_RATE		20
+#define SERIAL_GET_LINE_CONTROL		21
+#define SERIAL_GET_CHARS		22
+#define SERIAL_SET_CHARS		23
+#define SERIAL_GET_HANDFLOW		24
+#define SERIAL_SET_HANDFLOW		25
+#define SERIAL_GET_MODEMSTATUS		26
+#define SERIAL_GET_COMMSTATUS		27
+#define SERIAL_XOFF_COUNTER		28
+#define SERIAL_GET_PROPERTIES		29
+#define SERIAL_GET_DTRRTS		30
+#define SERIAL_LSRMST_INSERT		31
+#define SERIAL_CONFIG_SIZE		32
+#define SERIAL_GET_COMMCONFIG		33
+#define SERIAL_SET_COMMCONFIG		34
+#define SERIAL_GET_STATS		35
+#define SERIAL_CLEAR_STATS		36
+#define SERIAL_GET_MODEM_CONTROL	37
+#define SERIAL_SET_MODEM_CONTROL	38
+#define SERIAL_SET_FIFO_CONTROL		39
+
+#define STOP_BITS_1			0
+#define STOP_BITS_2			2
+
+#define NO_PARITY			0
+#define ODD_PARITY			1
+#define EVEN_PARITY			2
+
+#define SERIAL_PURGE_TXABORT 0x00000001
+#define SERIAL_PURGE_RXABORT 0x00000002
+#define SERIAL_PURGE_TXCLEAR 0x00000004
+#define SERIAL_PURGE_RXCLEAR 0x00000008
+
+/* SERIAL_WAIT_ON_MASK */
+#define SERIAL_EV_RXCHAR           0x0001	/* Any Character received */
+#define SERIAL_EV_RXFLAG           0x0002	/* Received certain character */
+#define SERIAL_EV_TXEMPTY          0x0004	/* Transmitt Queue Empty */
+#define SERIAL_EV_CTS              0x0008	/* CTS changed state */
+#define SERIAL_EV_DSR              0x0010	/* DSR changed state */
+#define SERIAL_EV_RLSD             0x0020	/* RLSD changed state */
+#define SERIAL_EV_BREAK            0x0040	/* BREAK received */
+#define SERIAL_EV_ERR              0x0080	/* Line status error occurred */
+#define SERIAL_EV_RING             0x0100	/* Ring signal detected */
+#define SERIAL_EV_PERR             0x0200	/* Printer error occured */
+#define SERIAL_EV_RX80FULL         0x0400	/* Receive buffer is 80 percent full */
+#define SERIAL_EV_EVENT1           0x0800	/* Provider specific event 1 */
+#define SERIAL_EV_EVENT2           0x1000	/* Provider specific event 2 */
+
+/* Modem Status */
+#define SERIAL_MS_DTR 0x01
+#define SERIAL_MS_RTS 0x02
+#define SERIAL_MS_CTS 0x10
+#define SERIAL_MS_DSR 0x20
+#define SERIAL_MS_RNG 0x40
+#define SERIAL_MS_CAR 0x80
+
+/* Handflow */
+#define SERIAL_DTR_CONTROL	0x01
+#define SERIAL_CTS_HANDSHAKE	0x08
+#define SERIAL_ERROR_ABORT	0x80000000
+
+#define SERIAL_XON_HANDSHAKE	0x01
+#define SERIAL_XOFF_HANDSHAKE	0x02
+#define SERIAL_DSR_SENSITIVITY	0x40
+
+#define SERIAL_CHAR_EOF		0
+#define SERIAL_CHAR_ERROR	1
+#define SERIAL_CHAR_BREAK	2
+#define SERIAL_CHAR_EVENT	3
+#define SERIAL_CHAR_XON		4
+#define SERIAL_CHAR_XOFF	5
+
+#ifndef CRTSCTS
+#define CRTSCTS 0
+#endif
+
+/* FIONREAD should really do the same thing as TIOCINQ, where it is
+ * not available */
+#if !defined(TIOCINQ) && defined(FIONREAD)
+#define TIOCINQ FIONREAD
+#endif
+#if !defined(TIOCOUTQ) && defined(FIONWRITE)
+#define TIOCOUTQ FIONWRITE
+#endif
+
+extern RDPDR_DEVICE g_rdpdr_device[];
+
+static SERIAL_DEVICE *
+get_serial_info(RD_NTHANDLE handle)
+{
+	int index;
+
+	for (index = 0; index < RDPDR_MAX_DEVICES; index++)
+	{
+		if (handle == g_rdpdr_device[index].handle)
+			return (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
+	}
+	return NULL;
+}
+
+static RD_BOOL
+get_termios(SERIAL_DEVICE * pser_inf, RD_NTHANDLE serial_fd)
+{
+	speed_t speed;
+	struct termios *ptermios;
+
+	ptermios = pser_inf->ptermios;
+
+	if (tcgetattr(serial_fd, ptermios) == -1)
+		return False;
+
+	speed = cfgetispeed(ptermios);
+	switch (speed)
+	{
+#ifdef B75
+		case B75:
+			pser_inf->baud_rate = 75;
+			break;
+#endif
+#ifdef B110
+		case B110:
+			pser_inf->baud_rate = 110;
+			break;
+#endif
+#ifdef B134
+		case B134:
+			pser_inf->baud_rate = 134;
+			break;
+#endif
+#ifdef B150
+		case B150:
+			pser_inf->baud_rate = 150;
+			break;
+#endif
+#ifdef B300
+		case B300:
+			pser_inf->baud_rate = 300;
+			break;
+#endif
+#ifdef B600
+		case B600:
+			pser_inf->baud_rate = 600;
+			break;
+#endif
+#ifdef B1200
+		case B1200:
+			pser_inf->baud_rate = 1200;
+			break;
+#endif
+#ifdef B1800
+		case B1800:
+			pser_inf->baud_rate = 1800;
+			break;
+#endif
+#ifdef B2400
+		case B2400:
+			pser_inf->baud_rate = 2400;
+			break;
+#endif
+#ifdef B4800
+		case B4800:
+			pser_inf->baud_rate = 4800;
+			break;
+#endif
+#ifdef B9600
+		case B9600:
+			pser_inf->baud_rate = 9600;
+			break;
+#endif
+#ifdef B19200
+		case B19200:
+			pser_inf->baud_rate = 19200;
+			break;
+#endif
+#ifdef B38400
+		case B38400:
+			pser_inf->baud_rate = 38400;
+			break;
+#endif
+#ifdef B57600
+		case B57600:
+			pser_inf->baud_rate = 57600;
+			break;
+#endif
+#ifdef B115200
+		case B115200:
+			pser_inf->baud_rate = 115200;
+			break;
+#endif
+#ifdef B230400
+		case B230400:
+			pser_inf->baud_rate = 230400;
+			break;
+#endif
+#ifdef B460800
+		case B460800:
+			pser_inf->baud_rate = 460800;
+			break;
+#endif
+		default:
+			pser_inf->baud_rate = 9600;
+			break;
+	}
+
+	speed = cfgetospeed(ptermios);
+	pser_inf->dtr = (speed == B0) ? 0 : 1;
+
+	pser_inf->stop_bits = (ptermios->c_cflag & CSTOPB) ? STOP_BITS_2 : STOP_BITS_1;
+	pser_inf->parity =
+		(ptermios->c_cflag & PARENB) ? ((ptermios->c_cflag & PARODD) ? ODD_PARITY :
+						EVEN_PARITY) : NO_PARITY;
+	switch (ptermios->c_cflag & CSIZE)
+	{
+		case CS5:
+			pser_inf->word_length = 5;
+			break;
+		case CS6:
+			pser_inf->word_length = 6;
+			break;
+		case CS7:
+			pser_inf->word_length = 7;
+			break;
+		default:
+			pser_inf->word_length = 8;
+			break;
+	}
+
+	if (ptermios->c_cflag & CRTSCTS)
+	{
+		pser_inf->control = SERIAL_DTR_CONTROL | SERIAL_CTS_HANDSHAKE | SERIAL_ERROR_ABORT;
+	}
+	else
+	{
+		pser_inf->control = SERIAL_DTR_CONTROL | SERIAL_ERROR_ABORT;
+	}
+
+	pser_inf->xonoff = SERIAL_DSR_SENSITIVITY;
+	if (ptermios->c_iflag & IXON)
+		pser_inf->xonoff |= SERIAL_XON_HANDSHAKE;
+
+	if (ptermios->c_iflag & IXOFF)
+		pser_inf->xonoff |= SERIAL_XOFF_HANDSHAKE;
+
+	pser_inf->chars[SERIAL_CHAR_XON] = ptermios->c_cc[VSTART];
+	pser_inf->chars[SERIAL_CHAR_XOFF] = ptermios->c_cc[VSTOP];
+	pser_inf->chars[SERIAL_CHAR_EOF] = ptermios->c_cc[VEOF];
+	pser_inf->chars[SERIAL_CHAR_BREAK] = ptermios->c_cc[VINTR];
+	pser_inf->chars[SERIAL_CHAR_ERROR] = ptermios->c_cc[VKILL];
+
+	return True;
+}
+
+static void
+set_termios(SERIAL_DEVICE * pser_inf, RD_NTHANDLE serial_fd)
+{
+	speed_t speed;
+
+	struct termios *ptermios;
+
+	ptermios = pser_inf->ptermios;
+
+
+	switch (pser_inf->baud_rate)
+	{
+#ifdef B75
+		case 75:
+			speed = B75;
+			break;
+#endif
+#ifdef B110
+		case 110:
+			speed = B110;
+			break;
+#endif
+#ifdef B134
+		case 134:
+			speed = B134;
+			break;
+#endif
+#ifdef B150
+		case 150:
+			speed = B150;
+			break;
+#endif
+#ifdef B300
+		case 300:
+			speed = B300;
+			break;
+#endif
+#ifdef B600
+		case 600:
+			speed = B600;
+			break;
+#endif
+#ifdef B1200
+		case 1200:
+			speed = B1200;
+			break;
+#endif
+#ifdef B1800
+		case 1800:
+			speed = B1800;
+			break;
+#endif
+#ifdef B2400
+		case 2400:
+			speed = B2400;
+			break;
+#endif
+#ifdef B4800
+		case 4800:
+			speed = B4800;
+			break;
+#endif
+#ifdef B9600
+		case 9600:
+			speed = B9600;
+			break;
+#endif
+#ifdef B19200
+		case 19200:
+			speed = B19200;
+			break;
+#endif
+#ifdef B38400
+		case 38400:
+			speed = B38400;
+			break;
+#endif
+#ifdef B57600
+		case 57600:
+			speed = B57600;
+			break;
+#endif
+#ifdef B115200
+		case 115200:
+			speed = B115200;
+			break;
+#endif
+#ifdef B230400
+		case 230400:
+			speed = B115200;
+			break;
+#endif
+#ifdef B460800
+		case 460800:
+			speed = B115200;
+			break;
+#endif
+		default:
+			speed = B9600;
+			break;
+	}
+
+#ifdef CBAUD
+	ptermios->c_cflag &= ~CBAUD;
+	ptermios->c_cflag |= speed;
+#else
+	/* on systems with separate ispeed and ospeed, we can remember the speed
+	   in ispeed while changing DTR with ospeed */
+	cfsetispeed(pser_inf->ptermios, speed);
+	cfsetospeed(pser_inf->ptermios, pser_inf->dtr ? speed : 0);
+#endif
+
+	ptermios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE | CRTSCTS);
+	switch (pser_inf->stop_bits)
+	{
+		case STOP_BITS_2:
+			ptermios->c_cflag |= CSTOPB;
+			break;
+		default:
+			ptermios->c_cflag &= ~CSTOPB;
+			break;
+	}
+
+	switch (pser_inf->parity)
+	{
+		case EVEN_PARITY:
+			ptermios->c_cflag |= PARENB;
+			break;
+		case ODD_PARITY:
+			ptermios->c_cflag |= PARENB | PARODD;
+			break;
+		case NO_PARITY:
+			ptermios->c_cflag &= ~(PARENB | PARODD);
+			break;
+	}
+
+	switch (pser_inf->word_length)
+	{
+		case 5:
+			ptermios->c_cflag |= CS5;
+			break;
+		case 6:
+			ptermios->c_cflag |= CS6;
+			break;
+		case 7:
+			ptermios->c_cflag |= CS7;
+			break;
+		default:
+			ptermios->c_cflag |= CS8;
+			break;
+	}
+
+#if 0
+	if (pser_inf->rts)
+		ptermios->c_cflag |= CRTSCTS;
+	else
+		ptermios->c_cflag &= ~CRTSCTS;
+#endif
+
+	if (pser_inf->control & SERIAL_CTS_HANDSHAKE)
+	{
+		ptermios->c_cflag |= CRTSCTS;
+	}
+	else
+	{
+		ptermios->c_cflag &= ~CRTSCTS;
+	}
+
+
+	if (pser_inf->xonoff & SERIAL_XON_HANDSHAKE)
+	{
+		ptermios->c_iflag |= IXON | IMAXBEL;
+	}
+	if (pser_inf->xonoff & SERIAL_XOFF_HANDSHAKE)
+	{
+		ptermios->c_iflag |= IXOFF | IMAXBEL;
+	}
+
+	if ((pser_inf->xonoff & (SERIAL_XOFF_HANDSHAKE | SERIAL_XON_HANDSHAKE)) == 0)
+	{
+		ptermios->c_iflag &= ~IXON;
+		ptermios->c_iflag &= ~IXOFF;
+	}
+
+	ptermios->c_cc[VSTART] = pser_inf->chars[SERIAL_CHAR_XON];
+	ptermios->c_cc[VSTOP] = pser_inf->chars[SERIAL_CHAR_XOFF];
+	ptermios->c_cc[VEOF] = pser_inf->chars[SERIAL_CHAR_EOF];
+	ptermios->c_cc[VINTR] = pser_inf->chars[SERIAL_CHAR_BREAK];
+	ptermios->c_cc[VKILL] = pser_inf->chars[SERIAL_CHAR_ERROR];
+
+	tcsetattr(serial_fd, TCSANOW, ptermios);
+}
+
+/* Enumeration of devices from rdesktop.c        */
+/* returns numer of units found and initialized. */
+/* optarg looks like ':com1=/dev/ttyS0'           */
+/* when it arrives to this function.              */
+/* :com1=/dev/ttyS0,com2=/dev/ttyS1 */
+int
+serial_enum_devices(uint32 * id, char *optarg)
+{
+	SERIAL_DEVICE *pser_inf;
+
+	char *pos = optarg;
+	char *pos2;
+	int count = 0;
+
+	/* skip the first colon */
+	optarg++;
+	while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
+	{
+		/* Init data structures for device */
+		pser_inf = (SERIAL_DEVICE *) xmalloc(sizeof(SERIAL_DEVICE));
+		pser_inf->ptermios = (struct termios *) xmalloc(sizeof(struct termios));
+		memset(pser_inf->ptermios, 0, sizeof(struct termios));
+		pser_inf->pold_termios = (struct termios *) xmalloc(sizeof(struct termios));
+		memset(pser_inf->pold_termios, 0, sizeof(struct termios));
+
+		pos2 = next_arg(optarg, '=');
+		strcpy(g_rdpdr_device[*id].name, optarg);
+
+		toupper_str(g_rdpdr_device[*id].name);
+
+		g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
+		strcpy(g_rdpdr_device[*id].local_path, pos2);
+		printf("SERIAL %s to %s\n", g_rdpdr_device[*id].name,
+		       g_rdpdr_device[*id].local_path);
+		/* set device type */
+		g_rdpdr_device[*id].device_type = DEVICE_TYPE_SERIAL;
+		g_rdpdr_device[*id].pdevice_data = (void *) pser_inf;
+		count++;
+		(*id)++;
+
+		optarg = pos;
+	}
+	return count;
+}
+
+static RD_NTSTATUS
+serial_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,
+	      uint32 flags_and_attributes, char *filename, RD_NTHANDLE * handle)
+{
+	RD_NTHANDLE serial_fd;
+	SERIAL_DEVICE *pser_inf;
+	struct termios *ptermios;
+
+	pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[device_id].pdevice_data;
+	ptermios = pser_inf->ptermios;
+	serial_fd = open(g_rdpdr_device[device_id].local_path, O_RDWR | O_NOCTTY | O_NONBLOCK);
+
+	if (serial_fd == -1)
+	{
+		perror("open");
+		return RD_STATUS_ACCESS_DENIED;
+	}
+
+	if (!get_termios(pser_inf, serial_fd))
+	{
+		printf("INFO: SERIAL %s access denied\n", g_rdpdr_device[device_id].name);
+		fflush(stdout);
+		return RD_STATUS_ACCESS_DENIED;
+	}
+
+	/* Store handle for later use */
+	g_rdpdr_device[device_id].handle = serial_fd;
+
+	/* some sane information */
+	DEBUG_SERIAL(("INFO: SERIAL %s to %s\nINFO: speed %u baud, stop bits %u, parity %u, word length %u bits, dtr %u, rts %u\n", g_rdpdr_device[device_id].name, g_rdpdr_device[device_id].local_path, pser_inf->baud_rate, pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length, pser_inf->dtr, pser_inf->rts));
+
+	pser_inf->ptermios->c_iflag &=
+		~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
+	pser_inf->ptermios->c_oflag &= ~OPOST;
+	pser_inf->ptermios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+	pser_inf->ptermios->c_cflag &= ~(CSIZE | PARENB);
+	pser_inf->ptermios->c_cflag |= CS8;
+
+	tcsetattr(serial_fd, TCSANOW, pser_inf->ptermios);
+
+	pser_inf->event_txempty = 0;
+	pser_inf->event_cts = 0;
+	pser_inf->event_dsr = 0;
+	pser_inf->event_rlsd = 0;
+	pser_inf->event_pending = 0;
+
+	*handle = serial_fd;
+
+	/* all read and writes should be non blocking */
+	if (fcntl(*handle, F_SETFL, O_NONBLOCK) == -1)
+		perror("fcntl");
+
+	pser_inf->read_total_timeout_constant = 5;
+
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+serial_close(RD_NTHANDLE handle)
+{
+	int i = get_device_index(handle);
+	if (i >= 0)
+		g_rdpdr_device[i].handle = 0;
+
+	rdpdr_abort_io(handle, 0, RD_STATUS_TIMEOUT);
+	close(handle);
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+serial_read(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
+{
+	long timeout;
+	SERIAL_DEVICE *pser_inf;
+	struct termios *ptermios;
+#ifdef WITH_DEBUG_SERIAL
+	int bytes_inqueue;
+#endif
+
+
+	timeout = 90;
+	pser_inf = get_serial_info(handle);
+	ptermios = pser_inf->ptermios;
+
+	/* Set timeouts kind of like the windows serial timeout parameters. Multiply timeout
+	   with requested read size */
+	if (pser_inf->read_total_timeout_multiplier | pser_inf->read_total_timeout_constant)
+	{
+		timeout =
+			(pser_inf->read_total_timeout_multiplier * length +
+			 pser_inf->read_total_timeout_constant + 99) / 100;
+	}
+	else if (pser_inf->read_interval_timeout)
+	{
+		timeout = (pser_inf->read_interval_timeout * length + 99) / 100;
+	}
+
+	/* If a timeout is set, do a blocking read, which times out after some time.
+	   It will make rdesktop less responsive, but it will improve serial performance, by not
+	   reading one character at a time. */
+	if (timeout == 0)
+	{
+		ptermios->c_cc[VTIME] = 0;
+		ptermios->c_cc[VMIN] = 0;
+	}
+	else
+	{
+		ptermios->c_cc[VTIME] = timeout;
+		ptermios->c_cc[VMIN] = 1;
+	}
+	tcsetattr(handle, TCSANOW, ptermios);
+
+#if defined(WITH_DEBUG_SERIAL) && defined(TIOCINQ)
+	ioctl(handle, TIOCINQ, &bytes_inqueue);
+	DEBUG_SERIAL(("serial_read inqueue: %d expected %d\n", bytes_inqueue, length));
+#endif
+
+	*result = read(handle, data, length);
+
+#ifdef WITH_DEBUG_SERIAL
+	DEBUG_SERIAL(("serial_read Bytes %d\n", *result));
+	if (*result > 0)
+		hexdump(data, *result);
+#endif
+
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+serial_write(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
+{
+	SERIAL_DEVICE *pser_inf;
+
+	pser_inf = get_serial_info(handle);
+
+	*result = write(handle, data, length);
+
+	if (*result > 0)
+		pser_inf->event_txempty = *result;
+
+	DEBUG_SERIAL(("serial_write length %d, offset %d result %d\n", length, offset, *result));
+
+	return RD_STATUS_SUCCESS;
+}
+
+static RD_NTSTATUS
+serial_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
+{
+	int purge_mask;
+	uint32 result, modemstate;
+	uint8 immediate;
+	SERIAL_DEVICE *pser_inf;
+	struct termios *ptermios;
+
+	if ((request >> 16) != FILE_DEVICE_SERIAL_PORT)
+		return RD_STATUS_INVALID_PARAMETER;
+
+	pser_inf = get_serial_info(handle);
+	ptermios = pser_inf->ptermios;
+
+	/* extract operation */
+	request >>= 2;
+	request &= 0xfff;
+
+	switch (request)
+	{
+		case SERIAL_SET_BAUD_RATE:
+			in_uint32_le(in, pser_inf->baud_rate);
+			set_termios(pser_inf, handle);
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BAUD_RATE %d\n",
+				      pser_inf->baud_rate));
+			break;
+		case SERIAL_GET_BAUD_RATE:
+			out_uint32_le(out, pser_inf->baud_rate);
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_BAUD_RATE %d\n",
+				      pser_inf->baud_rate));
+			break;
+		case SERIAL_SET_QUEUE_SIZE:
+			in_uint32_le(in, pser_inf->queue_in_size);
+			in_uint32_le(in, pser_inf->queue_out_size);
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_QUEUE_SIZE in %d out %d\n",
+				      pser_inf->queue_in_size, pser_inf->queue_out_size));
+			break;
+		case SERIAL_SET_LINE_CONTROL:
+			in_uint8(in, pser_inf->stop_bits);
+			in_uint8(in, pser_inf->parity);
+			in_uint8(in, pser_inf->word_length);
+			set_termios(pser_inf, handle);
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_LINE_CONTROL stop %d parity %d word %d\n", pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length));
+			break;
+		case SERIAL_GET_LINE_CONTROL:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_LINE_CONTROL\n"));
+			out_uint8(out, pser_inf->stop_bits);
+			out_uint8(out, pser_inf->parity);
+			out_uint8(out, pser_inf->word_length);
+			break;
+		case SERIAL_IMMEDIATE_CHAR:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_IMMEDIATE_CHAR\n"));
+			in_uint8(in, immediate);
+			serial_write(handle, &immediate, 1, 0, &result);
+			break;
+		case SERIAL_CONFIG_SIZE:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_CONFIG_SIZE\n"));
+			out_uint32_le(out, 0);
+			break;
+		case SERIAL_GET_CHARS:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_CHARS\n"));
+			out_uint8a(out, pser_inf->chars, 6);
+			break;
+		case SERIAL_SET_CHARS:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_CHARS\n"));
+			in_uint8a(in, pser_inf->chars, 6);
+#ifdef WITH_DEBUG_SERIAL
+			hexdump(pser_inf->chars, 6);
+#endif
+			set_termios(pser_inf, handle);
+			break;
+		case SERIAL_GET_HANDFLOW:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_HANDFLOW\n"));
+			get_termios(pser_inf, handle);
+			out_uint32_le(out, pser_inf->control);
+			out_uint32_le(out, pser_inf->xonoff);	/* Xon/Xoff */
+			out_uint32_le(out, pser_inf->onlimit);
+			out_uint32_le(out, pser_inf->offlimit);
+			break;
+		case SERIAL_SET_HANDFLOW:
+			in_uint32_le(in, pser_inf->control);
+			in_uint32_le(in, pser_inf->xonoff);
+			in_uint32_le(in, pser_inf->onlimit);
+			in_uint32_le(in, pser_inf->offlimit);
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_HANDFLOW %x %x %x %x\n",
+				      pser_inf->control, pser_inf->xonoff, pser_inf->onlimit,
+				      pser_inf->onlimit));
+			set_termios(pser_inf, handle);
+			break;
+		case SERIAL_SET_TIMEOUTS:
+			in_uint32(in, pser_inf->read_interval_timeout);
+			in_uint32(in, pser_inf->read_total_timeout_multiplier);
+			in_uint32(in, pser_inf->read_total_timeout_constant);
+			in_uint32(in, pser_inf->write_total_timeout_multiplier);
+			in_uint32(in, pser_inf->write_total_timeout_constant);
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_TIMEOUTS read timeout %d %d %d\n",
+				      pser_inf->read_interval_timeout,
+				      pser_inf->read_total_timeout_multiplier,
+				      pser_inf->read_total_timeout_constant));
+			break;
+		case SERIAL_GET_TIMEOUTS:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_TIMEOUTS read timeout %d %d %d\n",
+				      pser_inf->read_interval_timeout,
+				      pser_inf->read_total_timeout_multiplier,
+				      pser_inf->read_total_timeout_constant));
+
+			out_uint32(out, pser_inf->read_interval_timeout);
+			out_uint32(out, pser_inf->read_total_timeout_multiplier);
+			out_uint32(out, pser_inf->read_total_timeout_constant);
+			out_uint32(out, pser_inf->write_total_timeout_multiplier);
+			out_uint32(out, pser_inf->write_total_timeout_constant);
+			break;
+		case SERIAL_GET_WAIT_MASK:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_WAIT_MASK %X\n",
+				      pser_inf->wait_mask));
+			out_uint32(out, pser_inf->wait_mask);
+			break;
+		case SERIAL_SET_WAIT_MASK:
+			in_uint32(in, pser_inf->wait_mask);
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_WAIT_MASK %X\n",
+				      pser_inf->wait_mask));
+			break;
+		case SERIAL_SET_DTR:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_DTR\n"));
+			ioctl(handle, TIOCMGET, &result);
+			result |= TIOCM_DTR;
+			ioctl(handle, TIOCMSET, &result);
+			pser_inf->dtr = 1;
+			break;
+		case SERIAL_CLR_DTR:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_DTR\n"));
+			ioctl(handle, TIOCMGET, &result);
+			result &= ~TIOCM_DTR;
+			ioctl(handle, TIOCMSET, &result);
+			pser_inf->dtr = 0;
+			break;
+		case SERIAL_SET_RTS:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_RTS\n"));
+			ioctl(handle, TIOCMGET, &result);
+			result |= TIOCM_RTS;
+			ioctl(handle, TIOCMSET, &result);
+			pser_inf->rts = 1;
+			break;
+		case SERIAL_CLR_RTS:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_RTS\n"));
+			ioctl(handle, TIOCMGET, &result);
+			result &= ~TIOCM_RTS;
+			ioctl(handle, TIOCMSET, &result);
+			pser_inf->rts = 0;
+			break;
+		case SERIAL_GET_MODEMSTATUS:
+			modemstate = 0;
+#ifdef TIOCMGET
+			ioctl(handle, TIOCMGET, &result);
+			if (result & TIOCM_CTS)
+				modemstate |= SERIAL_MS_CTS;
+			if (result & TIOCM_DSR)
+				modemstate |= SERIAL_MS_DSR;
+			if (result & TIOCM_RNG)
+				modemstate |= SERIAL_MS_RNG;
+			if (result & TIOCM_CAR)
+				modemstate |= SERIAL_MS_CAR;
+			if (result & TIOCM_DTR)
+				modemstate |= SERIAL_MS_DTR;
+			if (result & TIOCM_RTS)
+				modemstate |= SERIAL_MS_RTS;
+#endif
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_MODEMSTATUS %X\n", modemstate));
+			out_uint32_le(out, modemstate);
+			break;
+		case SERIAL_GET_COMMSTATUS:
+			out_uint32_le(out, 0);	/* Errors */
+			out_uint32_le(out, 0);	/* Hold reasons */
+
+			result = 0;
+#ifdef TIOCINQ
+			ioctl(handle, TIOCINQ, &result);
+#endif
+			out_uint32_le(out, result);	/* Amount in in queue */
+			if (result)
+				DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS in queue %d\n",
+					      result));
+
+			result = 0;
+#ifdef TIOCOUTQ
+			ioctl(handle, TIOCOUTQ, &result);
+#endif
+			out_uint32_le(out, result);	/* Amount in out queue */
+			if (result)
+				DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS out queue %d\n", result));
+
+			out_uint8(out, 0);	/* EofReceived */
+			out_uint8(out, 0);	/* WaitForImmediate */
+			break;
+		case SERIAL_PURGE:
+			in_uint32(in, purge_mask);
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_PURGE purge_mask %X\n", purge_mask));
+			if ((purge_mask & SERIAL_PURGE_TXCLEAR)
+			    && (purge_mask & SERIAL_PURGE_RXCLEAR))
+				tcflush(handle, TCIOFLUSH);
+			else if (purge_mask & SERIAL_PURGE_TXCLEAR)
+				tcflush(handle, TCOFLUSH);
+			else if (purge_mask & SERIAL_PURGE_RXCLEAR)
+				tcflush(handle, TCIFLUSH);
+			if (purge_mask & SERIAL_PURGE_TXABORT)
+				rdpdr_abort_io(handle, 4, RD_STATUS_CANCELLED);
+			if (purge_mask & SERIAL_PURGE_RXABORT)
+				rdpdr_abort_io(handle, 3, RD_STATUS_CANCELLED);
+			break;
+		case SERIAL_WAIT_ON_MASK:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_WAIT_ON_MASK %X\n",
+				      pser_inf->wait_mask));
+			pser_inf->event_pending = 1;
+			if (serial_get_event(handle, &result))
+			{
+				DEBUG_SERIAL(("WAIT end  event = %x\n", result));
+				out_uint32_le(out, result);
+				break;
+			}
+			return RD_STATUS_PENDING;
+			break;
+		case SERIAL_SET_BREAK_ON:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_ON\n"));
+			tcsendbreak(handle, 0);
+			break;
+		case SERIAL_RESET_DEVICE:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_RESET_DEVICE\n"));
+			break;
+		case SERIAL_SET_BREAK_OFF:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_OFF\n"));
+			break;
+		case SERIAL_SET_XOFF:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XOFF\n"));
+			break;
+		case SERIAL_SET_XON:
+			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XON\n"));
+			tcflow(handle, TCION);
+			break;
+		default:
+			unimpl("SERIAL IOCTL %d\n", request);
+			return RD_STATUS_INVALID_PARAMETER;
+	}
+
+	return RD_STATUS_SUCCESS;
+}
+
+RD_BOOL
+serial_get_event(RD_NTHANDLE handle, uint32 * result)
+{
+	int index;
+	SERIAL_DEVICE *pser_inf;
+	int bytes;
+	RD_BOOL ret = False;
+
+	*result = 0;
+	index = get_device_index(handle);
+	if (index < 0)
+		return False;
+
+#ifdef TIOCINQ
+	pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
+
+	ioctl(handle, TIOCINQ, &bytes);
+
+	if (bytes > 0)
+	{
+		DEBUG_SERIAL(("serial_get_event Bytes %d\n", bytes));
+		if (bytes > pser_inf->event_rlsd)
+		{
+			pser_inf->event_rlsd = bytes;
+			if (pser_inf->wait_mask & SERIAL_EV_RLSD)
+			{
+				DEBUG_SERIAL(("Event -> SERIAL_EV_RLSD \n"));
+				*result |= SERIAL_EV_RLSD;
+				ret = True;
+			}
+
+		}
+
+		if ((bytes > 1) && (pser_inf->wait_mask & SERIAL_EV_RXFLAG))
+		{
+			DEBUG_SERIAL(("Event -> SERIAL_EV_RXFLAG Bytes %d\n", bytes));
+			*result |= SERIAL_EV_RXFLAG;
+			ret = True;
+		}
+		if ((pser_inf->wait_mask & SERIAL_EV_RXCHAR))
+		{
+			DEBUG_SERIAL(("Event -> SERIAL_EV_RXCHAR Bytes %d\n", bytes));
+			*result |= SERIAL_EV_RXCHAR;
+			ret = True;
+		}
+
+	}
+	else
+	{
+		pser_inf->event_rlsd = 0;
+	}
+#endif
+
+#ifdef TIOCOUTQ
+	ioctl(handle, TIOCOUTQ, &bytes);
+	if ((bytes == 0)
+	    && (pser_inf->event_txempty > 0) && (pser_inf->wait_mask & SERIAL_EV_TXEMPTY))
+	{
+
+		DEBUG_SERIAL(("Event -> SERIAL_EV_TXEMPTY\n"));
+		*result |= SERIAL_EV_TXEMPTY;
+		ret = True;
+	}
+	pser_inf->event_txempty = bytes;
+#endif
+
+	ioctl(handle, TIOCMGET, &bytes);
+	if ((bytes & TIOCM_DSR) != pser_inf->event_dsr)
+	{
+		pser_inf->event_dsr = bytes & TIOCM_DSR;
+		if (pser_inf->wait_mask & SERIAL_EV_DSR)
+		{
+			DEBUG_SERIAL(("event -> SERIAL_EV_DSR %s\n",
+				      (bytes & TIOCM_DSR) ? "ON" : "OFF"));
+			*result |= SERIAL_EV_DSR;
+			ret = True;
+		}
+	}
+
+	if ((bytes & TIOCM_CTS) != pser_inf->event_cts)
+	{
+		pser_inf->event_cts = bytes & TIOCM_CTS;
+		if (pser_inf->wait_mask & SERIAL_EV_CTS)
+		{
+			DEBUG_SERIAL((" EVENT-> SERIAL_EV_CTS %s\n",
+				      (bytes & TIOCM_CTS) ? "ON" : "OFF"));
+			*result |= SERIAL_EV_CTS;
+			ret = True;
+		}
+	}
+
+	if (ret)
+		pser_inf->event_pending = 0;
+
+	return ret;
+}
+
+/* Read timeout for a given file descripter (device) when adding fd's to select() */
+RD_BOOL
+serial_get_timeout(RD_NTHANDLE handle, uint32 length, uint32 * timeout, uint32 * itv_timeout)
+{
+	int index;
+	SERIAL_DEVICE *pser_inf;
+
+	index = get_device_index(handle);
+	if (index < 0)
+		return True;
+
+	if (g_rdpdr_device[index].device_type != DEVICE_TYPE_SERIAL)
+	{
+		return False;
+	}
+
+	pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
+
+	*timeout =
+		pser_inf->read_total_timeout_multiplier * length +
+		pser_inf->read_total_timeout_constant;
+	*itv_timeout = pser_inf->read_interval_timeout;
+	return True;
+}
+
+DEVICE_FNS serial_fns = {
+	serial_create,
+	serial_close,
+	serial_read,
+	serial_write,
+	serial_device_control
+};
Index: /trunk/src/VBox/RDP/client-1.8.3/ssl.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/ssl.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/ssl.c	(revision 55121)
@@ -0,0 +1,236 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Secure sockets abstraction layer
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright (C) Jay Sorg <j@american-data.com> 2006-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "rdesktop.h"
+#include "ssl.h"
+
+void
+rdssl_sha1_init(RDSSL_SHA1 * sha1)
+{
+	SHA1_Init(sha1);
+}
+
+void
+rdssl_sha1_update(RDSSL_SHA1 * sha1, uint8 * data, uint32 len)
+{
+	SHA1_Update(sha1, data, len);
+}
+
+void
+rdssl_sha1_final(RDSSL_SHA1 * sha1, uint8 * out_data)
+{
+	SHA1_Final(out_data, sha1);
+}
+
+void
+rdssl_md5_init(RDSSL_MD5 * md5)
+{
+	MD5_Init(md5);
+}
+
+void
+rdssl_md5_update(RDSSL_MD5 * md5, uint8 * data, uint32 len)
+{
+	MD5_Update(md5, data, len);
+}
+
+void
+rdssl_md5_final(RDSSL_MD5 * md5, uint8 * out_data)
+{
+	MD5_Final(out_data, md5);
+}
+
+void
+rdssl_rc4_set_key(RDSSL_RC4 * rc4, uint8 * key, uint32 len)
+{
+	RC4_set_key(rc4, len, key);
+}
+
+void
+rdssl_rc4_crypt(RDSSL_RC4 * rc4, uint8 * in_data, uint8 * out_data, uint32 len)
+{
+	RC4(rc4, len, in_data, out_data);
+}
+
+static void
+reverse(uint8 * p, int len)
+{
+	int i, j;
+	uint8 temp;
+
+	for (i = 0, j = len - 1; i < j; i++, j--)
+	{
+		temp = p[i];
+		p[i] = p[j];
+		p[j] = temp;
+	}
+}
+
+void
+rdssl_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
+		  uint8 * exponent)
+{
+	BN_CTX *ctx;
+	BIGNUM mod, exp, x, y;
+	uint8 inr[SEC_MAX_MODULUS_SIZE];
+	int outlen;
+
+	reverse(modulus, modulus_size);
+	reverse(exponent, SEC_EXPONENT_SIZE);
+	memcpy(inr, in, len);
+	reverse(inr, len);
+
+	ctx = BN_CTX_new();
+	BN_init(&mod);
+	BN_init(&exp);
+	BN_init(&x);
+	BN_init(&y);
+
+	BN_bin2bn(modulus, modulus_size, &mod);
+	BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
+	BN_bin2bn(inr, len, &x);
+	BN_mod_exp(&y, &x, &exp, &mod, ctx);
+	outlen = BN_bn2bin(&y, out);
+	reverse(out, outlen);
+	if (outlen < (int) modulus_size)
+		memset(out + outlen, 0, modulus_size - outlen);
+
+	BN_free(&y);
+	BN_clear_free(&x);
+	BN_free(&exp);
+	BN_free(&mod);
+	BN_CTX_free(ctx);
+}
+
+/* returns newly allocated RDSSL_CERT or NULL */
+RDSSL_CERT *
+rdssl_cert_read(uint8 * data, uint32 len)
+{
+	/* this will move the data pointer but we don't care, we don't use it again */
+	return d2i_X509(NULL, (D2I_X509_CONST unsigned char **) &data, len);
+}
+
+void
+rdssl_cert_free(RDSSL_CERT * cert)
+{
+	X509_free(cert);
+}
+
+/* returns newly allocated RDSSL_RKEY or NULL */
+RDSSL_RKEY *
+rdssl_cert_to_rkey(RDSSL_CERT * cert, uint32 * key_len)
+{
+	EVP_PKEY *epk = NULL;
+	RDSSL_RKEY *lkey;
+	int nid;
+
+	/* By some reason, Microsoft sets the OID of the Public RSA key to
+	   the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
+
+	   Kudos to Richard Levitte for the following (. intiutive .) 
+	   lines of code that resets the OID and let's us extract the key. */
+	nid = OBJ_obj2nid(cert->cert_info->key->algor->algorithm);
+	if ((nid == NID_md5WithRSAEncryption) || (nid == NID_shaWithRSAEncryption))
+	{
+		DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
+		ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);
+		cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
+	}
+	epk = X509_get_pubkey(cert);
+	if (NULL == epk)
+	{
+		error("Failed to extract public key from certificate\n");
+		return NULL;
+	}
+
+	lkey = RSAPublicKey_dup(EVP_PKEY_get1_RSA(epk));
+	EVP_PKEY_free(epk);
+	*key_len = RSA_size(lkey);
+	return lkey;
+}
+
+/* returns boolean */
+RD_BOOL
+rdssl_certs_ok(RDSSL_CERT * server_cert, RDSSL_CERT * cacert)
+{
+	/* Currently, we don't use the CA Certificate.
+	   FIXME:
+	   *) Verify the server certificate (server_cert) with the
+	   CA certificate.
+	   *) Store the CA Certificate with the hostname of the
+	   server we are connecting to as key, and compare it
+	   when we connect the next time, in order to prevent
+	   MITM-attacks.
+	 */
+	return True;
+}
+
+int
+rdssl_cert_print_fp(FILE * fp, RDSSL_CERT * cert)
+{
+	return X509_print_fp(fp, cert);
+}
+
+void
+rdssl_rkey_free(RDSSL_RKEY * rkey)
+{
+	RSA_free(rkey);
+}
+
+/* returns error */
+int
+rdssl_rkey_get_exp_mod(RDSSL_RKEY * rkey, uint8 * exponent, uint32 max_exp_len, uint8 * modulus,
+		       uint32 max_mod_len)
+{
+	int len;
+
+	if ((BN_num_bytes(rkey->e) > (int) max_exp_len) ||
+	    (BN_num_bytes(rkey->n) > (int) max_mod_len))
+	{
+		return 1;
+	}
+	len = BN_bn2bin(rkey->e, exponent);
+	reverse(exponent, len);
+	len = BN_bn2bin(rkey->n, modulus);
+	reverse(modulus, len);
+	return 0;
+}
+
+/* returns boolean */
+RD_BOOL
+rdssl_sig_ok(uint8 * exponent, uint32 exp_len, uint8 * modulus, uint32 mod_len,
+	     uint8 * signature, uint32 sig_len)
+{
+	/* Currently, we don't check the signature
+	   FIXME:
+	 */
+	return True;
+}
+
+
+void
+rdssl_hmac_md5(const void *key, int key_len, const unsigned char *msg, int msg_len,
+	       unsigned char *md)
+{
+	HMAC_CTX ctx;
+	HMAC_CTX_init(&ctx);
+	HMAC(EVP_md5(), key, key_len, msg, msg_len, md, NULL);
+	HMAC_CTX_cleanup(&ctx);
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/ssl.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/ssl.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/ssl.h	(revision 55121)
@@ -0,0 +1,67 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Secure sockets abstraction layer
+   Copyright (C) Matthew Chapman 1999-2008
+   Copyright (C) Jay Sorg 2006-2008
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _RDSSL_H
+#define _RDSSL_H
+
+#include <openssl/rc4.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#include <openssl/bn.h>
+#include <openssl/x509v3.h>
+#include <openssl/hmac.h>
+
+#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800f)
+#define D2I_X509_CONST const
+#else
+#define D2I_X509_CONST
+#endif
+
+#define RDSSL_RC4 RC4_KEY
+#define RDSSL_SHA1 SHA_CTX
+#define RDSSL_MD5 MD5_CTX
+#define RDSSL_CERT X509
+#define RDSSL_RKEY RSA
+
+void rdssl_sha1_init(RDSSL_SHA1 * sha1);
+void rdssl_sha1_update(RDSSL_SHA1 * sha1, uint8 * data, uint32 len);
+void rdssl_sha1_final(RDSSL_SHA1 * sha1, uint8 * out_data);
+void rdssl_md5_init(RDSSL_MD5 * md5);
+void rdssl_md5_update(RDSSL_MD5 * md5, uint8 * data, uint32 len);
+void rdssl_md5_final(RDSSL_MD5 * md5, uint8 * out_data);
+void rdssl_rc4_set_key(RDSSL_RC4 * rc4, uint8 * key, uint32 len);
+void rdssl_rc4_crypt(RDSSL_RC4 * rc4, uint8 * in_data, uint8 * out_data, uint32 len);
+void rdssl_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
+		       uint8 * exponent);
+RDSSL_CERT *rdssl_cert_read(uint8 * data, uint32 len);
+void rdssl_cert_free(RDSSL_CERT * cert);
+RDSSL_RKEY *rdssl_cert_to_rkey(RDSSL_CERT * cert, uint32 * key_len);
+RD_BOOL rdssl_certs_ok(RDSSL_CERT * server_cert, RDSSL_CERT * cacert);
+int rdssl_cert_print_fp(FILE * fp, RDSSL_CERT * cert);
+void rdssl_rkey_free(RDSSL_RKEY * rkey);
+int rdssl_rkey_get_exp_mod(RDSSL_RKEY * rkey, uint8 * exponent, uint32 max_exp_len, uint8 * modulus,
+			   uint32 max_mod_len);
+RD_BOOL rdssl_sig_ok(uint8 * exponent, uint32 exp_len, uint8 * modulus, uint32 mod_len,
+		     uint8 * signature, uint32 sig_len);
+
+void rdssl_hmac_md5(const void *key, int key_len,
+		    const unsigned char *msg, int msg_len, unsigned char *md);
+
+#endif
Index: /trunk/src/VBox/RDP/client-1.8.3/tcp.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/tcp.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/tcp.c	(revision 55121)
@@ -0,0 +1,614 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - TCP layer
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+   Copyright 2012-2013 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _WIN32
+#include <unistd.h>		/* select read write close */
+#include <sys/socket.h>		/* socket connect setsockopt */
+#include <sys/time.h>		/* timeval */
+#include <netdb.h>		/* gethostbyname */
+#include <netinet/in.h>		/* sockaddr_in */
+#include <netinet/tcp.h>	/* TCP_NODELAY */
+#include <arpa/inet.h>		/* inet_addr */
+#include <errno.h>		/* errno */
+#endif
+
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+#include <openssl/err.h>
+
+#include "rdesktop.h"
+
+#ifdef _WIN32
+#define socklen_t int
+#define TCP_CLOSE(_sck) closesocket(_sck)
+#define TCP_STRERROR "tcp error"
+#define TCP_BLOCKS (WSAGetLastError() == WSAEWOULDBLOCK)
+#else
+#define TCP_CLOSE(_sck) close(_sck)
+#define TCP_STRERROR strerror(errno)
+#define TCP_BLOCKS (errno == EWOULDBLOCK)
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE ((unsigned long) -1)
+#endif
+
+#ifdef WITH_SCARD
+#define STREAM_COUNT 8
+#else
+#define STREAM_COUNT 1
+#endif
+
+static RD_BOOL g_ssl_initialized = False;
+static SSL *g_ssl = NULL;
+static SSL_CTX *g_ssl_ctx = NULL;
+static int g_sock;
+static RD_BOOL g_run_ui = False;
+static struct stream g_in;
+static struct stream g_out[STREAM_COUNT];
+int g_tcp_port_rdp = TCP_PORT_RDP;
+extern RD_BOOL g_user_quit;
+extern RD_BOOL g_network_error;
+extern RD_BOOL g_reconnect_loop;
+
+/* wait till socket is ready to write or timeout */
+static RD_BOOL
+tcp_can_send(int sck, int millis)
+{
+	fd_set wfds;
+	struct timeval time;
+	int sel_count;
+
+	time.tv_sec = millis / 1000;
+	time.tv_usec = (millis * 1000) % 1000000;
+	FD_ZERO(&wfds);
+	FD_SET(sck, &wfds);
+	sel_count = select(sck + 1, 0, &wfds, 0, &time);
+	if (sel_count > 0)
+	{
+		return True;
+	}
+	return False;
+}
+
+/* Initialise TCP transport data packet */
+STREAM
+tcp_init(uint32 maxlen)
+{
+	static int cur_stream_id = 0;
+	STREAM result = NULL;
+
+#ifdef WITH_SCARD
+	scard_lock(SCARD_LOCK_TCP);
+#endif
+	result = &g_out[cur_stream_id];
+	cur_stream_id = (cur_stream_id + 1) % STREAM_COUNT;
+
+	if (maxlen > result->size)
+	{
+		result->data = (uint8 *) xrealloc(result->data, maxlen);
+		result->size = maxlen;
+	}
+
+	result->p = result->data;
+	result->end = result->data + result->size;
+#ifdef WITH_SCARD
+	scard_unlock(SCARD_LOCK_TCP);
+#endif
+	return result;
+}
+
+/* Send TCP transport data packet */
+void
+tcp_send(STREAM s)
+{
+	int ssl_err;
+	int length = s->end - s->data;
+	int sent, total = 0;
+
+	if (g_network_error == True)
+		return;
+
+#ifdef WITH_SCARD
+	scard_lock(SCARD_LOCK_TCP);
+#endif
+	while (total < length)
+	{
+		if (g_ssl)
+		{
+			sent = SSL_write(g_ssl, s->data + total, length - total);
+			if (sent <= 0)
+			{
+				ssl_err = SSL_get_error(g_ssl, sent);
+				if (sent < 0 && (ssl_err == SSL_ERROR_WANT_READ ||
+						 ssl_err == SSL_ERROR_WANT_WRITE))
+				{
+					tcp_can_send(g_sock, 100);
+					sent = 0;
+				}
+				else
+				{
+#ifdef WITH_SCARD
+					scard_unlock(SCARD_LOCK_TCP);
+#endif
+
+					error("SSL_write: %d (%s)\n", ssl_err, TCP_STRERROR);
+					g_network_error = True;
+					return;
+				}
+			}
+		}
+		else
+		{
+			sent = send(g_sock, s->data + total, length - total, 0);
+			if (sent <= 0)
+			{
+				if (sent == -1 && TCP_BLOCKS)
+				{
+					tcp_can_send(g_sock, 100);
+					sent = 0;
+				}
+				else
+				{
+#ifdef WITH_SCARD
+					scard_unlock(SCARD_LOCK_TCP);
+#endif
+
+					error("send: %s\n", TCP_STRERROR);
+					g_network_error = True;
+					return;
+				}
+			}
+		}
+		total += sent;
+	}
+#ifdef WITH_SCARD
+	scard_unlock(SCARD_LOCK_TCP);
+#endif
+}
+
+/* Receive a message on the TCP layer */
+STREAM
+tcp_recv(STREAM s, uint32 length)
+{
+	uint32 new_length, end_offset, p_offset;
+	int rcvd = 0, ssl_err;
+
+	if (g_network_error == True)
+		return NULL;
+
+	if (s == NULL)
+	{
+		/* read into "new" stream */
+		if (length > g_in.size)
+		{
+			g_in.data = (uint8 *) xrealloc(g_in.data, length);
+			g_in.size = length;
+		}
+		g_in.end = g_in.p = g_in.data;
+		s = &g_in;
+	}
+	else
+	{
+		/* append to existing stream */
+		new_length = (s->end - s->data) + length;
+		if (new_length > s->size)
+		{
+			p_offset = s->p - s->data;
+			end_offset = s->end - s->data;
+			s->data = (uint8 *) xrealloc(s->data, new_length);
+			s->size = new_length;
+			s->p = s->data + p_offset;
+			s->end = s->data + end_offset;
+		}
+	}
+
+	while (length > 0)
+	{
+		if ((!g_ssl || SSL_pending(g_ssl) <= 0) && g_run_ui)
+		{
+			if (!ui_select(g_sock))
+			{
+				/* User quit */
+				g_user_quit = True;
+				return NULL;
+			}
+		}
+
+		if (g_ssl)
+		{
+			rcvd = SSL_read(g_ssl, s->end, length);
+			ssl_err = SSL_get_error(g_ssl, rcvd);
+
+			if (ssl_err == SSL_ERROR_SSL)
+			{
+				if (SSL_get_shutdown(g_ssl) & SSL_RECEIVED_SHUTDOWN)
+				{
+					error("Remote peer initiated ssl shutdown.\n");
+					return NULL;
+				}
+
+				ERR_print_errors_fp(stdout);
+				g_network_error = True;
+				return NULL;
+			}
+
+			if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE)
+			{
+				rcvd = 0;
+			}
+			else if (ssl_err != SSL_ERROR_NONE)
+			{
+				error("SSL_read: %d (%s)\n", ssl_err, TCP_STRERROR);
+				g_network_error = True;
+				return NULL;
+			}
+
+		}
+		else
+		{
+			rcvd = recv(g_sock, s->end, length, 0);
+			if (rcvd < 0)
+			{
+				if (rcvd == -1 && TCP_BLOCKS)
+				{
+					rcvd = 0;
+				}
+				else
+				{
+					error("recv: %s\n", TCP_STRERROR);
+					g_network_error = True;
+					return NULL;
+				}
+			}
+			else if (rcvd == 0)
+			{
+				error("Connection closed\n");
+				return NULL;
+			}
+		}
+
+		s->end += rcvd;
+		length -= rcvd;
+	}
+
+	return s;
+}
+
+/* Establish a SSL/TLS 1.0 connection */
+RD_BOOL
+tcp_tls_connect(void)
+{
+	int err;
+	long options;
+
+	if (!g_ssl_initialized)
+	{
+		SSL_load_error_strings();
+		SSL_library_init();
+		g_ssl_initialized = True;
+	}
+
+	/* create process context */
+	if (g_ssl_ctx == NULL)
+	{
+		g_ssl_ctx = SSL_CTX_new(TLSv1_client_method());
+		if (g_ssl_ctx == NULL)
+		{
+			error("tcp_tls_connect: SSL_CTX_new() failed to create TLS v1.0 context\n");
+			goto fail;
+		}
+
+		options = 0;
+#ifdef SSL_OP_NO_COMPRESSION
+		options |= SSL_OP_NO_COMPRESSION;
+#endif // __SSL_OP_NO_COMPRESSION
+		options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+		SSL_CTX_set_options(g_ssl_ctx, options);
+	}
+
+	/* free old connection */
+	if (g_ssl)
+		SSL_free(g_ssl);
+
+	/* create new ssl connection */
+	g_ssl = SSL_new(g_ssl_ctx);
+	if (g_ssl == NULL)
+	{
+		error("tcp_tls_connect: SSL_new() failed\n");
+		goto fail;
+	}
+
+	if (SSL_set_fd(g_ssl, g_sock) < 1)
+	{
+		error("tcp_tls_connect: SSL_set_fd() failed\n");
+		goto fail;
+	}
+
+	do
+	{
+		err = SSL_connect(g_ssl);
+	}
+	while (SSL_get_error(g_ssl, err) == SSL_ERROR_WANT_READ);
+
+	if (err < 0)
+	{
+		ERR_print_errors_fp(stdout);
+		goto fail;
+	}
+
+	return True;
+
+      fail:
+	if (g_ssl)
+		SSL_free(g_ssl);
+	if (g_ssl_ctx)
+		SSL_CTX_free(g_ssl_ctx);
+
+	g_ssl = NULL;
+	g_ssl_ctx = NULL;
+	return False;
+}
+
+/* Get public key from server of TLS 1.0 connection */
+RD_BOOL
+tcp_tls_get_server_pubkey(STREAM s)
+{
+	X509 *cert = NULL;
+	EVP_PKEY *pkey = NULL;
+
+	s->data = s->p = NULL;
+	s->size = 0;
+
+	if (g_ssl == NULL)
+		goto out;
+
+	cert = SSL_get_peer_certificate(g_ssl);
+	if (cert == NULL)
+	{
+		error("tcp_tls_get_server_pubkey: SSL_get_peer_certificate() failed\n");
+		goto out;
+	}
+
+	pkey = X509_get_pubkey(cert);
+	if (pkey == NULL)
+	{
+		error("tcp_tls_get_server_pubkey: X509_get_pubkey() failed\n");
+		goto out;
+	}
+
+	s->size = i2d_PublicKey(pkey, NULL);
+	if (s->size < 1)
+	{
+		error("tcp_tls_get_server_pubkey: i2d_PublicKey() failed\n");
+		goto out;
+	}
+
+	s->data = s->p = xmalloc(s->size);
+	i2d_PublicKey(pkey, &s->p);
+	s->p = s->data;
+	s->end = s->p + s->size;
+
+      out:
+	if (cert)
+		X509_free(cert);
+	if (pkey)
+		EVP_PKEY_free(pkey);
+	return (s->size != 0);
+}
+
+/* Establish a connection on the TCP layer */
+RD_BOOL
+tcp_connect(char *server)
+{
+	socklen_t option_len;
+	uint32 option_value;
+	int i;
+
+#ifdef IPv6
+
+	int n;
+	struct addrinfo hints, *res, *ressave;
+	char tcp_port_rdp_s[10];
+
+	snprintf(tcp_port_rdp_s, 10, "%d", g_tcp_port_rdp);
+
+	memset(&hints, 0, sizeof(struct addrinfo));
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+
+	if ((n = getaddrinfo(server, tcp_port_rdp_s, &hints, &res)))
+	{
+		error("getaddrinfo: %s\n", gai_strerror(n));
+		return False;
+	}
+
+	ressave = res;
+	g_sock = -1;
+	while (res)
+	{
+		g_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+		if (!(g_sock < 0))
+		{
+			if (connect(g_sock, res->ai_addr, res->ai_addrlen) == 0)
+				break;
+			TCP_CLOSE(g_sock);
+			g_sock = -1;
+		}
+		res = res->ai_next;
+	}
+	freeaddrinfo(ressave);
+
+	if (g_sock == -1)
+	{
+		error("%s: unable to connect\n", server);
+		return False;
+	}
+
+#else /* no IPv6 support */
+
+	struct hostent *nslookup;
+	struct sockaddr_in servaddr;
+
+	if ((nslookup = gethostbyname(server)) != NULL)
+	{
+		memcpy(&servaddr.sin_addr, nslookup->h_addr, sizeof(servaddr.sin_addr));
+	}
+	else if ((servaddr.sin_addr.s_addr = inet_addr(server)) == INADDR_NONE)
+	{
+		error("%s: unable to resolve host\n", server);
+		return False;
+	}
+
+	if ((g_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+	{
+		error("socket: %s\n", TCP_STRERROR);
+		return False;
+	}
+
+	servaddr.sin_family = AF_INET;
+	servaddr.sin_port = htons((uint16) g_tcp_port_rdp);
+
+	if (connect(g_sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0)
+	{
+		if (!g_reconnect_loop)
+			error("connect: %s\n", TCP_STRERROR);
+
+		TCP_CLOSE(g_sock);
+		g_sock = -1;
+		return False;
+	}
+
+#endif /* IPv6 */
+
+	option_value = 1;
+	option_len = sizeof(option_value);
+	setsockopt(g_sock, IPPROTO_TCP, TCP_NODELAY, (void *) &option_value, option_len);
+	/* receive buffer must be a least 16 K */
+	if (getsockopt(g_sock, SOL_SOCKET, SO_RCVBUF, (void *) &option_value, &option_len) == 0)
+	{
+		if (option_value < (1024 * 16))
+		{
+			option_value = 1024 * 16;
+			option_len = sizeof(option_value);
+			setsockopt(g_sock, SOL_SOCKET, SO_RCVBUF, (void *) &option_value,
+				   option_len);
+		}
+	}
+
+	g_in.size = 4096;
+	g_in.data = (uint8 *) xmalloc(g_in.size);
+
+	for (i = 0; i < STREAM_COUNT; i++)
+	{
+		g_out[i].size = 4096;
+		g_out[i].data = (uint8 *) xmalloc(g_out[i].size);
+	}
+
+	return True;
+}
+
+/* Disconnect on the TCP layer */
+void
+tcp_disconnect(void)
+{
+	if (g_ssl)
+	{
+		if (!g_network_error)
+			(void) SSL_shutdown(g_ssl);
+		SSL_free(g_ssl);
+		g_ssl = NULL;
+		SSL_CTX_free(g_ssl_ctx);
+		g_ssl_ctx = NULL;
+	}
+
+	TCP_CLOSE(g_sock);
+	g_sock = -1;
+}
+
+char *
+tcp_get_address()
+{
+	static char ipaddr[32];
+	struct sockaddr_in sockaddr;
+	socklen_t len = sizeof(sockaddr);
+	if (getsockname(g_sock, (struct sockaddr *) &sockaddr, &len) == 0)
+	{
+		uint8 *ip = (uint8 *) & sockaddr.sin_addr;
+		sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+	}
+	else
+		strcpy(ipaddr, "127.0.0.1");
+	return ipaddr;
+}
+
+RD_BOOL
+tcp_is_connected()
+{
+	struct sockaddr_in sockaddr;
+	socklen_t len = sizeof(sockaddr);
+	if (getpeername(g_sock, (struct sockaddr *) &sockaddr, &len))
+		return True;
+	return False;
+}
+
+/* reset the state of the tcp layer */
+/* Support for Session Directory */
+void
+tcp_reset_state(void)
+{
+	int i;
+
+	/* Clear the incoming stream */
+	if (g_in.data != NULL)
+		xfree(g_in.data);
+	g_in.p = NULL;
+	g_in.end = NULL;
+	g_in.data = NULL;
+	g_in.size = 0;
+	g_in.iso_hdr = NULL;
+	g_in.mcs_hdr = NULL;
+	g_in.sec_hdr = NULL;
+	g_in.rdp_hdr = NULL;
+	g_in.channel_hdr = NULL;
+
+	/* Clear the outgoing stream(s) */
+	for (i = 0; i < STREAM_COUNT; i++)
+	{
+		if (g_out[i].data != NULL)
+			xfree(g_out[i].data);
+		g_out[i].p = NULL;
+		g_out[i].end = NULL;
+		g_out[i].data = NULL;
+		g_out[i].size = 0;
+		g_out[i].iso_hdr = NULL;
+		g_out[i].mcs_hdr = NULL;
+		g_out[i].sec_hdr = NULL;
+		g_out[i].rdp_hdr = NULL;
+		g_out[i].channel_hdr = NULL;
+	}
+}
+
+void
+tcp_run_ui(RD_BOOL run)
+{
+	g_run_ui = run;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/types.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/types.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/types.h	(revision 55121)
@@ -0,0 +1,296 @@
+/*
+   rdesktop: A Remote Desktop Protocol client.
+   Common data types
+   Copyright (C) Matthew Chapman 1999-2008
+   Copyright 2014 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+typedef int RD_BOOL;
+
+#ifndef True
+#define True  (1)
+#define False (0)
+#endif
+
+typedef unsigned char uint8;
+typedef signed char sint8;
+typedef unsigned short uint16;
+typedef signed short sint16;
+typedef unsigned int uint32;
+typedef signed int sint32;
+
+typedef void *RD_HBITMAP;
+typedef void *RD_HGLYPH;
+typedef void *RD_HCOLOURMAP;
+typedef void *RD_HCURSOR;
+
+
+typedef enum _RDP_VERSION
+{
+	RDP_V4 = 4,
+	RDP_V5 = 5,
+	RDP_V6 = 6
+} RDP_VERSION;
+
+
+typedef struct _RD_POINT
+{
+	sint16 x, y;
+}
+RD_POINT;
+
+typedef struct _COLOURENTRY
+{
+	uint8 red;
+	uint8 green;
+	uint8 blue;
+
+}
+COLOURENTRY;
+
+typedef struct _COLOURMAP
+{
+	uint16 ncolours;
+	COLOURENTRY *colours;
+
+}
+COLOURMAP;
+
+typedef struct _BOUNDS
+{
+	sint16 left;
+	sint16 top;
+	sint16 right;
+	sint16 bottom;
+
+}
+BOUNDS;
+
+typedef struct _PEN
+{
+	uint8 style;
+	uint8 width;
+	uint32 colour;
+
+}
+PEN;
+
+/* this is whats in the brush cache */
+typedef struct _BRUSHDATA
+{
+	uint32 colour_code;
+	uint32 data_size;
+	uint8 *data;
+}
+BRUSHDATA;
+
+typedef struct _BRUSH
+{
+	uint8 xorigin;
+	uint8 yorigin;
+	uint8 style;
+	uint8 pattern[8];
+	BRUSHDATA *bd;
+}
+BRUSH;
+
+typedef struct _FONTGLYPH
+{
+	sint16 offset;
+	sint16 baseline;
+	uint16 width;
+	uint16 height;
+	RD_HBITMAP pixmap;
+
+}
+FONTGLYPH;
+
+typedef struct _DATABLOB
+{
+	void *data;
+	int size;
+
+}
+DATABLOB;
+
+typedef struct _key_translation
+{
+	/* For normal scancode translations */
+	uint8 scancode;
+	uint16 modifiers;
+	/* For sequences. If keysym is nonzero, the fields above are not used. */
+	uint32 seq_keysym;	/* Really KeySym */
+	struct _key_translation *next;
+}
+key_translation;
+
+typedef struct _key_translation_entry
+{
+	key_translation *tr;
+	/* The full KeySym for this entry, not KEYMAP_MASKed */
+	uint32 keysym;
+	/* This will be non-NULL if there has been a hash collision */
+	struct _key_translation_entry *next;
+}
+key_translation_entry;
+
+typedef struct _VCHANNEL
+{
+	uint16 mcs_id;
+	char name[8];
+	uint32 flags;
+	struct stream in;
+	void (*process) (STREAM);
+}
+VCHANNEL;
+
+/* PSTCACHE */
+typedef uint8 HASH_KEY[8];
+
+/* Header for an entry in the persistent bitmap cache file */
+typedef struct _PSTCACHE_CELLHEADER
+{
+	HASH_KEY key;
+	uint8 width, height;
+	uint16 length;
+	uint32 stamp;
+}
+CELLHEADER;
+
+#define MAX_CBSIZE 256
+
+/* RDPSND */
+typedef struct _RD_WAVEFORMATEX
+{
+	uint16 wFormatTag;
+	uint16 nChannels;
+	uint32 nSamplesPerSec;
+	uint32 nAvgBytesPerSec;
+	uint16 nBlockAlign;
+	uint16 wBitsPerSample;
+	uint16 cbSize;
+	uint8 cb[MAX_CBSIZE];
+} RD_WAVEFORMATEX;
+
+typedef struct _RDPCOMP
+{
+	uint32 roff;
+	uint8 hist[RDP_MPPC_DICT_SIZE];
+	struct stream ns;
+}
+RDPCOMP;
+
+/* RDPDR */
+typedef uint32 RD_NTSTATUS;
+typedef uint32 RD_NTHANDLE;
+
+typedef struct _DEVICE_FNS
+{
+	RD_NTSTATUS(*create) (uint32 device, uint32 desired_access, uint32 share_mode,
+			      uint32 create_disposition, uint32 flags_and_attributes,
+			      char *filename, RD_NTHANDLE * handle);
+	RD_NTSTATUS(*close) (RD_NTHANDLE handle);
+	RD_NTSTATUS(*read) (RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset,
+			    uint32 * result);
+	RD_NTSTATUS(*write) (RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset,
+			     uint32 * result);
+	RD_NTSTATUS(*device_control) (RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out);
+}
+DEVICE_FNS;
+
+
+typedef struct rdpdr_device_info
+{
+	uint32 device_type;
+	RD_NTHANDLE handle;
+	char name[8];
+	char *local_path;
+	void *pdevice_data;
+}
+RDPDR_DEVICE;
+
+typedef struct rdpdr_serial_device_info
+{
+	int dtr;
+	int rts;
+	uint32 control, xonoff, onlimit, offlimit;
+	uint32 baud_rate,
+		queue_in_size,
+		queue_out_size,
+		wait_mask,
+		read_interval_timeout,
+		read_total_timeout_multiplier,
+		read_total_timeout_constant,
+		write_total_timeout_multiplier, write_total_timeout_constant, posix_wait_mask;
+	uint8 stop_bits, parity, word_length;
+	uint8 chars[6];
+	struct termios *ptermios, *pold_termios;
+	int event_txempty, event_cts, event_dsr, event_rlsd, event_pending;
+}
+SERIAL_DEVICE;
+
+typedef struct rdpdr_parallel_device_info
+{
+	char *driver, *printer;
+	uint32 queue_in_size,
+		queue_out_size,
+		wait_mask,
+		read_interval_timeout,
+		read_total_timeout_multiplier,
+		read_total_timeout_constant,
+		write_total_timeout_multiplier,
+		write_total_timeout_constant, posix_wait_mask, bloblen;
+	uint8 *blob;
+}
+PARALLEL_DEVICE;
+
+typedef struct rdpdr_printer_info
+{
+	FILE *printer_fp;
+	char *driver, *printer;
+	uint32 bloblen;
+	uint8 *blob;
+	RD_BOOL default_printer;
+}
+PRINTER;
+
+typedef struct notify_data
+{
+	time_t modify_time;
+	time_t status_time;
+	time_t total_time;
+	unsigned int num_entries;
+}
+NOTIFY;
+
+#ifndef PATH_MAX
+#define PATH_MAX 256
+#endif
+
+typedef struct fileinfo
+{
+	uint32 device_id, flags_and_attributes, accessmask;
+	char path[PATH_MAX];
+	DIR *pdir;
+	struct dirent *pdirent;
+	char pattern[PATH_MAX];
+	RD_BOOL delete_on_close;
+	NOTIFY notify;
+	uint32 info_class;
+}
+FILEINFO;
+
+typedef RD_BOOL(*str_handle_lines_t) (const char *line, void *data);
Index: /trunk/src/VBox/RDP/client-1.8.3/utils.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/utils.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/utils.c	(revision 55121)
@@ -0,0 +1,224 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Generic utility functions
+   Copyright 2013 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#ifdef HAVE_ICONV_H
+#include <iconv.h>
+#endif
+#include "rdesktop.h"
+
+
+#ifdef HAVE_ICONV
+extern char g_codepage[16];
+static RD_BOOL g_iconv_works = True;
+#endif
+
+
+
+char *
+utils_string_escape(const char *str)
+{
+	const char *p;
+	char *pe, *e, esc[4];
+	size_t es;
+	int cnt;
+
+	/* count indices */
+	cnt = 0;
+	p = str;
+	while (*(p++) != '\0')
+		if ((unsigned char) *p < 32 || *p == '%')
+			cnt++;
+
+	/* if no characters needs escaping return copy of str */
+	if (cnt == 0)
+		return strdup(str);
+
+	/* allocate new mem for result */
+	es = strlen(str) + (cnt * 3) + 1;
+	pe = e = xmalloc(es);
+	memset(e, 0, es);
+	p = str;
+	while (*p != '\0')
+	{
+		if ((unsigned char) *p < 32 || *p == '%')
+		{
+			snprintf(esc, 4, "%%%02X", *p);
+			memcpy(pe, esc, 3);
+			pe += 3;
+		}
+		else
+		{
+			*pe = *p;
+			pe++;
+		}
+
+		p++;
+	}
+
+	return e;
+}
+
+char *
+utils_string_unescape(const char *str)
+{
+	char *ns, *ps, *pd, c;
+
+	ns = xmalloc(strlen(str) + 1);
+	memcpy(ns, str, strlen(str) + 1);
+	ps = pd = ns;
+
+	while (*ps != '\0')
+	{
+		/* check if found escaped character */
+		if (ps[0] == '%')
+		{
+			if (sscanf(ps, "%%%2hhX", &c) == 1)
+			{
+				pd[0] = c;
+				ps += 3;
+				pd++;
+				continue;
+			}
+		}
+
+		/* just copy over the char */
+		*pd = *ps;
+		ps++;
+		pd++;
+	}
+	pd[0] = '\0';
+
+	return ns;
+}
+
+int
+utils_mkdir_safe(const char *path, int mask)
+{
+	int res = 0;
+	struct stat st;
+
+	res = stat(path, &st);
+	if (res == -1)
+		return mkdir(path, mask);
+
+	if (!S_ISDIR(st.st_mode))
+	{
+		errno = EEXIST;
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+utils_mkdir_p(const char *path, int mask)
+{
+	int res;
+	char *ptok;
+	char pt[PATH_MAX];
+	char bp[PATH_MAX];
+
+	if (!path || strlen(path) == 0)
+	{
+		errno = EINVAL;
+		return -1;
+	}
+	if (strlen(path) > PATH_MAX)
+	{
+		errno = E2BIG;
+		return -1;
+	}
+
+	res = 0;
+	pt[0] = bp[0] = '\0';
+	strcpy(bp, path);
+
+	ptok = strtok(bp, "/");
+	if (ptok == NULL)
+		return utils_mkdir_safe(path, mask);
+
+	do
+	{
+		if (ptok != bp)
+			strcat(pt, "/");
+
+		strcat(pt, ptok);
+		res = utils_mkdir_safe(pt, mask);
+		if (res != 0)
+			return res;
+
+	}
+	while ((ptok = strtok(NULL, "/")) != NULL);
+
+	return 0;
+}
+
+/* Convert from system locale string to utf-8 */
+int
+utils_locale_to_utf8(const char *src, size_t is, char *dest, size_t os)
+{
+#ifdef HAVE_ICONV
+	static iconv_t *iconv_h = (iconv_t) - 1;
+	if (strncmp(g_codepage, "UTF-8", strlen("UTF-8")) == 0)
+		goto pass_trough_as_is;
+
+	if (g_iconv_works == False)
+		goto pass_trough_as_is;
+
+	/* if not already initialize */
+	if (iconv_h == (iconv_t) - 1)
+	{
+		if ((iconv_h = iconv_open("UTF-8", g_codepage)) == (iconv_t) - 1)
+		{
+			warning("utils_string_to_utf8: iconv_open[%s -> %s] fail %p\n",
+				g_codepage, "UTF-8", iconv_h);
+
+			g_iconv_works = False;
+			goto pass_trough_as_is;
+		}
+	}
+
+	/* convert string */
+	if (iconv(iconv_h, (ICONV_CONST char **) &src, &is, &dest, &os) == (size_t) - 1)
+	{
+		iconv_close(iconv_h);
+		iconv_h = (iconv_t) - 1;
+		warning("utils_string_to_utf8: iconv(1) fail, errno %d\n", errno);
+
+		g_iconv_works = False;
+		goto pass_trough_as_is;
+	}
+
+	/* Out couldn't hold the entire convertion */
+	if (is != 0)
+		return -1;
+
+#endif
+      pass_trough_as_is:
+	/* can dest hold strcpy of src */
+	if (os < (strlen(src) + 1))
+		return -1;
+
+	memcpy(dest, src, strlen(src) + 1);
+	return 0;
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/xclip.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/xclip.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/xclip.c	(revision 55121)
@@ -0,0 +1,1196 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - Clipboard functions
+   Copyright 2003-2008 Erik Forsberg <forsberg@cendio.se> for Cendio AB
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
+   Copyright 2006-2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include "rdesktop.h"
+
+/*
+  To gain better understanding of this code, one could be assisted by the following documents:
+  - Inter-Client Communication Conventions Manual (ICCCM)
+    HTML: http://tronche.com/gui/x/icccm/
+    PDF:  http://ftp.xfree86.org/pub/XFree86/4.5.0/doc/PDF/icccm.pdf
+  - MSDN: Clipboard Formats
+    http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/dataexchange/clipboard/clipboardformats.asp
+*/
+
+#ifdef HAVE_ICONV
+#ifdef HAVE_LANGINFO_H
+#ifdef HAVE_ICONV_H
+#include <langinfo.h>
+#include <iconv.h>
+#define USE_UNICODE_CLIPBOARD
+#endif
+#endif
+#endif
+
+#ifdef USE_UNICODE_CLIPBOARD
+#define RDP_CF_TEXT CF_UNICODETEXT
+#else
+#define RDP_CF_TEXT CF_TEXT
+#endif
+
+#define MAX_TARGETS 8
+
+extern Display *g_display;
+extern Window g_wnd;
+extern Time g_last_gesturetime;
+extern RD_BOOL g_rdpclip;
+
+/* Mode of operation.
+   - Auto: Look at both PRIMARY and CLIPBOARD and use the most recent.
+   - Non-auto: Look at just CLIPBOARD. */
+static RD_BOOL auto_mode = True;
+/* Atoms of the two X selections we're dealing with: CLIPBOARD (explicit-copy) and PRIMARY (selection-copy) */
+static Atom clipboard_atom, primary_atom;
+/* Atom of the TARGETS clipboard target */
+static Atom targets_atom;
+/* Atom of the TIMESTAMP clipboard target */
+static Atom timestamp_atom;
+/* Atom _RDESKTOP_CLIPBOARD_TARGET which is used as the 'property' argument in
+   XConvertSelection calls: This is the property of our window into which
+   XConvertSelection will store the received clipboard data. */
+static Atom rdesktop_clipboard_target_atom;
+/* Atoms _RDESKTOP_PRIMARY_TIMESTAMP_TARGET and _RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET
+   are used to store the timestamps for when a window got ownership of the selections.
+   We use these to determine which is more recent and should be used. */
+static Atom rdesktop_primary_timestamp_target_atom, rdesktop_clipboard_timestamp_target_atom;
+/* Storage for timestamps since we get them in two separate notifications. */
+static Time primary_timestamp, clipboard_timestamp;
+/* Clipboard target for getting a list of native Windows clipboard formats. The
+   presence of this target indicates that the selection owner is another rdesktop. */
+static Atom rdesktop_clipboard_formats_atom;
+/* The clipboard target (X jargon for "clipboard format") for rdesktop-to-rdesktop
+   interchange of Windows native clipboard data. The requestor must supply the
+   desired native Windows clipboard format in the associated property. */
+static Atom rdesktop_native_atom;
+/* Local copy of the list of native Windows clipboard formats. */
+static uint8 *formats_data = NULL;
+static uint32 formats_data_length = 0;
+/* We need to know when another rdesktop process gets or loses ownership of a
+   selection. Without XFixes we do this by touching a property on the root window
+   which will generate PropertyNotify notifications. */
+static Atom rdesktop_selection_notify_atom;
+/* State variables that indicate if we're currently probing the targets of the
+   selection owner. reprobe_selections indicate that the ownership changed in
+   the middle of the current probe so it should be restarted. */
+static RD_BOOL probing_selections, reprobe_selections;
+/* Atoms _RDESKTOP_PRIMARY_OWNER and _RDESKTOP_CLIPBOARD_OWNER. Used as properties
+   on the root window to indicate which selections that are owned by rdesktop. */
+static Atom rdesktop_primary_owner_atom, rdesktop_clipboard_owner_atom;
+static Atom format_string_atom, format_utf8_string_atom, format_unicode_atom;
+/* Atom of the INCR clipboard type (see ICCCM on "INCR Properties") */
+static Atom incr_atom;
+/* Stores the last "selection request" (= another X client requesting clipboard data from us).
+   To satisfy such a request, we request the clipboard data from the RDP server.
+   When we receive the response from the RDP server (asynchronously), this variable gives us
+   the context to proceed. */
+static XSelectionRequestEvent selection_request;
+/* Denotes we have a pending selection request. */
+static RD_BOOL has_selection_request;
+/* Stores the clipboard format (CF_TEXT, CF_UNICODETEXT etc.) requested in the last
+   CLIPDR_DATA_REQUEST (= the RDP server requesting clipboard data from us).
+   When we receive this data from whatever X client offering it, this variable gives us
+   the context to proceed.
+ */
+static int rdp_clipboard_request_format;
+/* Array of offered clipboard targets that will be sent to fellow X clients upon a TARGETS request. */
+static Atom targets[MAX_TARGETS];
+static int num_targets;
+/* Denotes that an rdesktop (not this rdesktop) is owning the selection,
+   allowing us to interchange Windows native clipboard data directly. */
+static RD_BOOL rdesktop_is_selection_owner = False;
+/* Time when we acquired the selection. */
+static Time acquire_time = 0;
+
+/* Denotes that an INCR ("chunked") transfer is in progress. */
+static int g_waiting_for_INCR = 0;
+/* Denotes the target format of the ongoing INCR ("chunked") transfer. */
+static Atom g_incr_target = 0;
+/* Buffers an INCR transfer. */
+static uint8 *g_clip_buffer = 0;
+/* Denotes the size of g_clip_buffer. */
+static uint32 g_clip_buflen = 0;
+
+/* Translates CR-LF to LF.
+   Changes the string in-place.
+   Does not stop on embedded nulls.
+   The length is updated. */
+static void
+crlf2lf(uint8 * data, uint32 * length)
+{
+	uint8 *dst, *src;
+	src = dst = data;
+	while (src < data + *length)
+	{
+		if (*src != '\x0d')
+			*dst++ = *src;
+		src++;
+	}
+	*length = dst - data;
+}
+
+#ifdef USE_UNICODE_CLIPBOARD
+/* Translate LF to CR-LF. To do this, we must allocate more memory.
+   The returned string is null-terminated, as required by CF_UNICODETEXT.
+   The size is updated. */
+static uint8 *
+utf16_lf2crlf(uint8 * data, uint32 * size)
+{
+	uint8 *result;
+	uint16 *inptr, *outptr;
+	RD_BOOL swap_endianess;
+
+	/* Worst case: Every char is LF */
+	result = xmalloc((*size * 2) + 2);
+	if (result == NULL)
+		return NULL;
+
+	inptr = (uint16 *) data;
+	outptr = (uint16 *) result;
+
+	/* Check for a reversed BOM */
+	swap_endianess = (*inptr == 0xfffe);
+
+	uint16 uvalue_previous = 0;	/* Kept so we'll avoid translating CR-LF to CR-CR-LF */
+	while ((uint8 *) inptr < data + *size)
+	{
+		uint16 uvalue = *inptr;
+		if (swap_endianess)
+			uvalue = ((uvalue << 8) & 0xff00) + (uvalue >> 8);
+		if ((uvalue == 0x0a) && (uvalue_previous != 0x0d))
+			*outptr++ = swap_endianess ? 0x0d00 : 0x0d;
+		uvalue_previous = uvalue;
+		*outptr++ = *inptr++;
+	}
+	*outptr++ = 0;		/* null termination */
+	*size = (uint8 *) outptr - result;
+
+	return result;
+}
+#else
+/* Translate LF to CR-LF. To do this, we must allocate more memory.
+   The length is updated. */
+static uint8 *
+lf2crlf(uint8 * data, uint32 * length)
+{
+	uint8 *result, *p, *o;
+
+	/* Worst case: Every char is LF */
+	result = xmalloc(*length * 2);
+
+	p = data;
+	o = result;
+
+	uint8 previous = '\0';	/* Kept to avoid translating CR-LF to CR-CR-LF */
+	while (p < data + *length)
+	{
+		if ((*p == '\x0a') && (previous != '\x0d'))
+			*o++ = '\x0d';
+		previous = *p;
+		*o++ = *p++;
+	}
+	*length = o - result;
+
+	/* Convenience */
+	*o++ = '\0';
+
+	return result;
+}
+#endif
+
+static void
+xclip_provide_selection(XSelectionRequestEvent * req, Atom type, unsigned int format, uint8 * data,
+			uint32 length)
+{
+	XEvent xev;
+
+	DEBUG_CLIPBOARD(("xclip_provide_selection: requestor=0x%08x, target=%s, property=%s, length=%u\n", (unsigned) req->requestor, XGetAtomName(g_display, req->target), XGetAtomName(g_display, req->property), (unsigned) length));
+
+	XChangeProperty(g_display, req->requestor, req->property,
+			type, format, PropModeReplace, data, length);
+
+	xev.xselection.type = SelectionNotify;
+	xev.xselection.serial = 0;
+	xev.xselection.send_event = True;
+	xev.xselection.requestor = req->requestor;
+	xev.xselection.selection = req->selection;
+	xev.xselection.target = req->target;
+	xev.xselection.property = req->property;
+	xev.xselection.time = req->time;
+	XSendEvent(g_display, req->requestor, False, NoEventMask, &xev);
+}
+
+/* Replies a clipboard requestor, telling that we're unable to satisfy his request for whatever reason.
+   This has the benefit of finalizing the clipboard negotiation and thus not leaving our requestor
+   lingering (and, potentially, stuck). */
+static void
+xclip_refuse_selection(XSelectionRequestEvent * req)
+{
+	XEvent xev;
+
+	DEBUG_CLIPBOARD(("xclip_refuse_selection: requestor=0x%08x, target=%s, property=%s\n",
+			 (unsigned) req->requestor, XGetAtomName(g_display, req->target),
+			 XGetAtomName(g_display, req->property)));
+
+	xev.xselection.type = SelectionNotify;
+	xev.xselection.serial = 0;
+	xev.xselection.send_event = True;
+	xev.xselection.requestor = req->requestor;
+	xev.xselection.selection = req->selection;
+	xev.xselection.target = req->target;
+	xev.xselection.property = None;
+	xev.xselection.time = req->time;
+	XSendEvent(g_display, req->requestor, False, NoEventMask, &xev);
+}
+
+/* Wrapper for cliprdr_send_data which also cleans the request state. */
+static void
+helper_cliprdr_send_response(uint8 * data, uint32 length)
+{
+	if (rdp_clipboard_request_format != 0)
+	{
+		cliprdr_send_data(data, length);
+		rdp_clipboard_request_format = 0;
+		if (!rdesktop_is_selection_owner)
+			cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);
+	}
+}
+
+/* Last resort, when we have to provide clipboard data but for whatever
+   reason couldn't get any.
+ */
+static void
+helper_cliprdr_send_empty_response()
+{
+	helper_cliprdr_send_response(NULL, 0);
+}
+
+/* Replies with clipboard data to RDP, converting it from the target format
+   to the expected RDP format as necessary. Returns true if data was sent.
+ */
+static RD_BOOL
+xclip_send_data_with_convert(uint8 * source, size_t source_size, Atom target)
+{
+	DEBUG_CLIPBOARD(("xclip_send_data_with_convert: target=%s, size=%u\n",
+			 XGetAtomName(g_display, target), (unsigned) source_size));
+
+#ifdef USE_UNICODE_CLIPBOARD
+	if (target == format_string_atom ||
+	    target == format_unicode_atom || target == format_utf8_string_atom)
+	{
+		size_t unicode_buffer_size;
+		char *unicode_buffer;
+		iconv_t cd;
+		size_t unicode_buffer_size_remaining;
+		char *unicode_buffer_remaining;
+		char *data_remaining;
+		size_t data_size_remaining;
+		uint32 translated_data_size;
+		uint8 *translated_data;
+
+		if (rdp_clipboard_request_format != RDP_CF_TEXT)
+			return False;
+
+		/* Make an attempt to convert any string we send to Unicode.
+		   We don't know what the RDP server's ANSI Codepage is, or how to convert
+		   to it, so using CF_TEXT is not safe (and is unnecessary, since all
+		   WinNT versions are Unicode-minded).
+		 */
+		if (target == format_string_atom)
+		{
+			char *locale_charset = nl_langinfo(CODESET);
+			cd = iconv_open(WINDOWS_CODEPAGE, locale_charset);
+			if (cd == (iconv_t) - 1)
+			{
+				DEBUG_CLIPBOARD(("Locale charset %s not found in iconv. Unable to convert clipboard text.\n", locale_charset));
+				return False;
+			}
+			unicode_buffer_size = source_size * 4;
+		}
+		else if (target == format_unicode_atom)
+		{
+			cd = iconv_open(WINDOWS_CODEPAGE, "UCS-2");
+			if (cd == (iconv_t) - 1)
+			{
+				return False;
+			}
+			unicode_buffer_size = source_size;
+		}
+		else if (target == format_utf8_string_atom)
+		{
+			cd = iconv_open(WINDOWS_CODEPAGE, "UTF-8");
+			if (cd == (iconv_t) - 1)
+			{
+				return False;
+			}
+			/* UTF-8 is guaranteed to be less or equally compact
+			   as UTF-16 for all Unicode chars >=2 bytes.
+			 */
+			unicode_buffer_size = source_size * 2;
+		}
+		else
+		{
+			return False;
+		}
+
+		unicode_buffer = xmalloc(unicode_buffer_size);
+		unicode_buffer_size_remaining = unicode_buffer_size;
+		unicode_buffer_remaining = unicode_buffer;
+		data_remaining = (char *) source;
+		data_size_remaining = source_size;
+		iconv(cd, (ICONV_CONST char **) &data_remaining, &data_size_remaining,
+		      &unicode_buffer_remaining, &unicode_buffer_size_remaining);
+		iconv_close(cd);
+
+		/* translate linebreaks */
+		translated_data_size = unicode_buffer_size - unicode_buffer_size_remaining;
+		translated_data = utf16_lf2crlf((uint8 *) unicode_buffer, &translated_data_size);
+		if (translated_data != NULL)
+		{
+			DEBUG_CLIPBOARD(("Sending Unicode string of %d bytes\n",
+					 translated_data_size));
+			helper_cliprdr_send_response(translated_data, translated_data_size);
+			xfree(translated_data);	/* Not the same thing as XFree! */
+		}
+
+		xfree(unicode_buffer);
+
+		return True;
+	}
+#else
+	if (target == format_string_atom)
+	{
+		uint8 *translated_data;
+		uint32 length = source_size;
+
+		if (rdp_clipboard_request_format != RDP_CF_TEXT)
+			return False;
+
+		DEBUG_CLIPBOARD(("Translating linebreaks before sending data\n"));
+		translated_data = lf2crlf(source, &length);
+		if (translated_data != NULL)
+		{
+			helper_cliprdr_send_response(translated_data, length + 1);
+			xfree(translated_data);	/* Not the same thing as XFree! */
+		}
+
+		return True;
+	}
+#endif
+	else if (target == rdesktop_native_atom)
+	{
+		helper_cliprdr_send_response(source, source_size + 1);
+
+		return True;
+	}
+	else
+	{
+		return False;
+	}
+}
+
+static void
+xclip_clear_target_props()
+{
+	XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);
+	XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom);
+	XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom);
+}
+
+static void
+xclip_notify_change()
+{
+	XChangeProperty(g_display, DefaultRootWindow(g_display),
+			rdesktop_selection_notify_atom, XA_INTEGER, 32, PropModeReplace, NULL, 0);
+}
+
+static void
+xclip_probe_selections()
+{
+	Window primary_owner, clipboard_owner;
+
+	if (probing_selections)
+	{
+		DEBUG_CLIPBOARD(("Already probing selections. Scheduling reprobe.\n"));
+		reprobe_selections = True;
+		return;
+	}
+
+	DEBUG_CLIPBOARD(("Probing selections.\n"));
+
+	probing_selections = True;
+	reprobe_selections = False;
+
+	xclip_clear_target_props();
+
+	if (auto_mode)
+		primary_owner = XGetSelectionOwner(g_display, primary_atom);
+	else
+		primary_owner = None;
+
+	clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom);
+
+	/* If we own all relevant selections then don't do anything. */
+	if (((primary_owner == g_wnd) || !auto_mode) && (clipboard_owner == g_wnd))
+		goto end;
+
+	/* Both available */
+	if ((primary_owner != None) && (clipboard_owner != None))
+	{
+		primary_timestamp = 0;
+		clipboard_timestamp = 0;
+		XConvertSelection(g_display, primary_atom, timestamp_atom,
+				  rdesktop_primary_timestamp_target_atom, g_wnd, CurrentTime);
+		XConvertSelection(g_display, clipboard_atom, timestamp_atom,
+				  rdesktop_clipboard_timestamp_target_atom, g_wnd, CurrentTime);
+		return;
+	}
+
+	/* Just PRIMARY */
+	if (primary_owner != None)
+	{
+		XConvertSelection(g_display, primary_atom, targets_atom,
+				  rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
+		return;
+	}
+
+	/* Just CLIPBOARD */
+	if (clipboard_owner != None)
+	{
+		XConvertSelection(g_display, clipboard_atom, targets_atom,
+				  rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
+		return;
+	}
+
+	DEBUG_CLIPBOARD(("No owner of any selection.\n"));
+
+	/* FIXME:
+	   Without XFIXES, we cannot reliably know the formats offered by an
+	   upcoming selection owner, so we just lie about him offering
+	   RDP_CF_TEXT. */
+	cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);
+
+      end:
+	probing_selections = False;
+}
+
+/* This function is called for SelectionNotify events.
+   The SelectionNotify event is sent from the clipboard owner to the requestor
+   after his request was satisfied.
+   If this function is called, we're the requestor side. */
+#ifndef MAKE_PROTO
+void
+xclip_handle_SelectionNotify(XSelectionEvent * event)
+{
+	unsigned long nitems, bytes_left;
+	XWindowAttributes wa;
+	Atom type;
+	Atom *supported_targets;
+	int res, i, format;
+	uint8 *data = NULL;
+
+	if (event->property == None)
+		goto fail;
+
+	DEBUG_CLIPBOARD(("xclip_handle_SelectionNotify: selection=%s, target=%s, property=%s\n",
+			 XGetAtomName(g_display, event->selection),
+			 XGetAtomName(g_display, event->target),
+			 XGetAtomName(g_display, event->property)));
+
+	if (event->target == timestamp_atom)
+	{
+		if (event->selection == primary_atom)
+		{
+			res = XGetWindowProperty(g_display, g_wnd,
+						 rdesktop_primary_timestamp_target_atom, 0,
+						 XMaxRequestSize(g_display), False, AnyPropertyType,
+						 &type, &format, &nitems, &bytes_left, &data);
+		}
+		else
+		{
+			res = XGetWindowProperty(g_display, g_wnd,
+						 rdesktop_clipboard_timestamp_target_atom, 0,
+						 XMaxRequestSize(g_display), False, AnyPropertyType,
+						 &type, &format, &nitems, &bytes_left, &data);
+		}
+
+
+		if ((res != Success) || (nitems != 1) || (format != 32))
+		{
+			DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
+			goto fail;
+		}
+
+		if (event->selection == primary_atom)
+		{
+			primary_timestamp = *(Time *) data;
+			if (primary_timestamp == 0)
+				primary_timestamp++;
+			XDeleteProperty(g_display, g_wnd, rdesktop_primary_timestamp_target_atom);
+			DEBUG_CLIPBOARD(("Got PRIMARY timestamp: %u\n",
+					 (unsigned) primary_timestamp));
+		}
+		else
+		{
+			clipboard_timestamp = *(Time *) data;
+			if (clipboard_timestamp == 0)
+				clipboard_timestamp++;
+			XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_timestamp_target_atom);
+			DEBUG_CLIPBOARD(("Got CLIPBOARD timestamp: %u\n",
+					 (unsigned) clipboard_timestamp));
+		}
+
+		XFree(data);
+
+		if (primary_timestamp && clipboard_timestamp)
+		{
+			if (primary_timestamp > clipboard_timestamp)
+			{
+				DEBUG_CLIPBOARD(("PRIMARY is most recent selection.\n"));
+				XConvertSelection(g_display, primary_atom, targets_atom,
+						  rdesktop_clipboard_target_atom, g_wnd,
+						  event->time);
+			}
+			else
+			{
+				DEBUG_CLIPBOARD(("CLIPBOARD is most recent selection.\n"));
+				XConvertSelection(g_display, clipboard_atom, targets_atom,
+						  rdesktop_clipboard_target_atom, g_wnd,
+						  event->time);
+			}
+		}
+
+		return;
+	}
+
+	if (probing_selections && reprobe_selections)
+	{
+		probing_selections = False;
+		xclip_probe_selections();
+		return;
+	}
+
+	res = XGetWindowProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
+				 0, XMaxRequestSize(g_display), False, AnyPropertyType,
+				 &type, &format, &nitems, &bytes_left, &data);
+
+	xclip_clear_target_props();
+
+	if (res != Success)
+	{
+		DEBUG_CLIPBOARD(("XGetWindowProperty failed!\n"));
+		goto fail;
+	}
+
+	if (type == incr_atom)
+	{
+		DEBUG_CLIPBOARD(("Received INCR.\n"));
+
+		XGetWindowAttributes(g_display, g_wnd, &wa);
+		if ((wa.your_event_mask | PropertyChangeMask) != wa.your_event_mask)
+		{
+			XSelectInput(g_display, g_wnd, (wa.your_event_mask | PropertyChangeMask));
+		}
+		XFree(data);
+		g_incr_target = event->target;
+		g_waiting_for_INCR = 1;
+		goto end;
+	}
+
+	/* Negotiate target format */
+	if (event->target == targets_atom)
+	{
+		/* Determine the best of text targets that we have available:
+		   Prefer UTF8_STRING > text/unicode (unspecified encoding) > STRING
+		   (ignore TEXT and COMPOUND_TEXT because we don't have code to handle them)
+		 */
+		int text_target_satisfaction = 0;
+		Atom best_text_target = 0;	/* measures how much we're satisfied with what we found */
+		if (type != None)
+		{
+			supported_targets = (Atom *) data;
+			for (i = 0; i < nitems; i++)
+			{
+				DEBUG_CLIPBOARD(("Target %d: %s\n", i,
+						 XGetAtomName(g_display, supported_targets[i])));
+				if (supported_targets[i] == format_string_atom)
+				{
+					if (text_target_satisfaction < 1)
+					{
+						DEBUG_CLIPBOARD(("Other party supports STRING, choosing that as best_target\n"));
+						best_text_target = supported_targets[i];
+						text_target_satisfaction = 1;
+					}
+				}
+#ifdef USE_UNICODE_CLIPBOARD
+				else if (supported_targets[i] == format_unicode_atom)
+				{
+					if (text_target_satisfaction < 2)
+					{
+						DEBUG_CLIPBOARD(("Other party supports text/unicode, choosing that as best_target\n"));
+						best_text_target = supported_targets[i];
+						text_target_satisfaction = 2;
+					}
+				}
+				else if (supported_targets[i] == format_utf8_string_atom)
+				{
+					if (text_target_satisfaction < 3)
+					{
+						DEBUG_CLIPBOARD(("Other party supports UTF8_STRING, choosing that as best_target\n"));
+						best_text_target = supported_targets[i];
+						text_target_satisfaction = 3;
+					}
+				}
+#endif
+				else if (supported_targets[i] == rdesktop_clipboard_formats_atom)
+				{
+					if (probing_selections && (text_target_satisfaction < 4))
+					{
+						DEBUG_CLIPBOARD(("Other party supports native formats, choosing that as best_target\n"));
+						best_text_target = supported_targets[i];
+						text_target_satisfaction = 4;
+					}
+				}
+			}
+		}
+
+		/* Kickstarting the next step in the process of satisfying RDP's
+		   clipboard request -- specifically, requesting the actual clipboard data.
+		 */
+		if ((best_text_target != 0)
+		    && (!probing_selections
+			|| (best_text_target == rdesktop_clipboard_formats_atom)))
+		{
+			XConvertSelection(g_display, event->selection, best_text_target,
+					  rdesktop_clipboard_target_atom, g_wnd, event->time);
+			goto end;
+		}
+		else
+		{
+			DEBUG_CLIPBOARD(("Unable to find a textual target to satisfy RDP clipboard text request\n"));
+			goto fail;
+		}
+	}
+	else
+	{
+		if (probing_selections)
+		{
+			Window primary_owner, clipboard_owner;
+
+			/* FIXME:
+			   Without XFIXES, we must make sure that the other
+			   rdesktop owns all relevant selections or we might try
+			   to get a native format from non-rdesktop window later
+			   on. */
+
+			clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom);
+
+			if (auto_mode)
+				primary_owner = XGetSelectionOwner(g_display, primary_atom);
+			else
+				primary_owner = clipboard_owner;
+
+			if (primary_owner != clipboard_owner)
+				goto fail;
+
+			DEBUG_CLIPBOARD(("Got fellow rdesktop formats\n"));
+			probing_selections = False;
+			rdesktop_is_selection_owner = True;
+			cliprdr_send_native_format_announce(data, nitems);
+		}
+		else if ((!nitems) || (!xclip_send_data_with_convert(data, nitems, event->target)))
+		{
+			goto fail;
+		}
+	}
+
+      end:
+	if (data)
+		XFree(data);
+
+	return;
+
+      fail:
+	xclip_clear_target_props();
+	if (probing_selections)
+	{
+		DEBUG_CLIPBOARD(("Unable to find suitable target. Using default text format.\n"));
+		probing_selections = False;
+		rdesktop_is_selection_owner = False;
+
+		/* FIXME:
+		   Without XFIXES, we cannot reliably know the formats offered by an
+		   upcoming selection owner, so we just lie about him offering
+		   RDP_CF_TEXT. */
+		cliprdr_send_simple_native_format_announce(RDP_CF_TEXT);
+	}
+	else
+	{
+		helper_cliprdr_send_empty_response();
+	}
+	goto end;
+}
+
+/* This function is called for SelectionRequest events.
+   The SelectionRequest event is sent from the requestor to the clipboard owner
+   to request clipboard data.
+ */
+void
+xclip_handle_SelectionRequest(XSelectionRequestEvent * event)
+{
+	unsigned long nitems, bytes_left;
+	unsigned char *prop_return = NULL;
+	int format, res;
+	Atom type;
+
+	DEBUG_CLIPBOARD(("xclip_handle_SelectionRequest: selection=%s, target=%s, property=%s\n",
+			 XGetAtomName(g_display, event->selection),
+			 XGetAtomName(g_display, event->target),
+			 XGetAtomName(g_display, event->property)));
+
+	if (event->target == targets_atom)
+	{
+		xclip_provide_selection(event, XA_ATOM, 32, (uint8 *) & targets, num_targets);
+		return;
+	}
+	else if (event->target == timestamp_atom)
+	{
+		xclip_provide_selection(event, XA_INTEGER, 32, (uint8 *) & acquire_time, 1);
+		return;
+	}
+	else if (event->target == rdesktop_clipboard_formats_atom)
+	{
+		xclip_provide_selection(event, XA_STRING, 8, formats_data, formats_data_length);
+	}
+	else
+	{
+		/* All the following targets require an async operation with the RDP server
+		   and currently we don't do X clipboard request queueing so we can only
+		   handle one such request at a time. */
+		if (has_selection_request)
+		{
+			DEBUG_CLIPBOARD(("Error: Another clipboard request was already sent to the RDP server and not yet responded. Refusing this request.\n"));
+			xclip_refuse_selection(event);
+			return;
+		}
+		if (event->target == rdesktop_native_atom)
+		{
+			/* Before the requestor makes a request for the _RDESKTOP_NATIVE target,
+			   he should declare requestor[property] = CF_SOMETHING. */
+			res = XGetWindowProperty(g_display, event->requestor,
+						 event->property, 0, 1, True,
+						 XA_INTEGER, &type, &format, &nitems, &bytes_left,
+						 &prop_return);
+			if (res != Success || (!prop_return))
+			{
+				DEBUG_CLIPBOARD(("Requested native format but didn't specifiy which.\n"));
+				xclip_refuse_selection(event);
+				return;
+			}
+
+			format = *(uint32 *) prop_return;
+			XFree(prop_return);
+		}
+		else if (event->target == format_string_atom || event->target == XA_STRING)
+		{
+			/* STRING and XA_STRING are defined to be ISO8859-1 */
+			format = CF_TEXT;
+		}
+		else if (event->target == format_utf8_string_atom)
+		{
+#ifdef USE_UNICODE_CLIPBOARD
+			format = CF_UNICODETEXT;
+#else
+			DEBUG_CLIPBOARD(("Requested target unavailable due to lack of Unicode support. (It was not in TARGETS, so why did you ask for it?!)\n"));
+			xclip_refuse_selection(event);
+			return;
+#endif
+		}
+		else if (event->target == format_unicode_atom)
+		{
+			/* Assuming text/unicode to be UTF-16 */
+			format = CF_UNICODETEXT;
+		}
+		else
+		{
+			DEBUG_CLIPBOARD(("Requested target unavailable. (It was not in TARGETS, so why did you ask for it?!)\n"));
+			xclip_refuse_selection(event);
+			return;
+		}
+
+		cliprdr_send_data_request(format);
+		selection_request = *event;
+		has_selection_request = True;
+		return;		/* wait for data */
+	}
+}
+
+/* While this rdesktop holds ownership over the clipboard, it means the clipboard data
+   is offered by the RDP server (and when it is pasted inside RDP, there's no network
+   roundtrip).
+
+   This event (SelectionClear) symbolizes this rdesktop lost onwership of the clipboard
+   to some other X client. We should find out what clipboard formats this other
+   client offers and announce that to RDP. */
+void
+xclip_handle_SelectionClear(void)
+{
+	DEBUG_CLIPBOARD(("xclip_handle_SelectionClear\n"));
+	xclip_notify_change();
+	xclip_probe_selections();
+}
+
+/* Called when any property changes in our window or the root window. */
+void
+xclip_handle_PropertyNotify(XPropertyEvent * event)
+{
+	unsigned long nitems;
+	unsigned long offset = 0;
+	unsigned long bytes_left = 1;
+	int format;
+	XWindowAttributes wa;
+	uint8 *data;
+	Atom type;
+
+	if (event->state == PropertyNewValue && g_waiting_for_INCR)
+	{
+		DEBUG_CLIPBOARD(("x_clip_handle_PropertyNotify: g_waiting_for_INCR != 0\n"));
+
+		while (bytes_left > 0)
+		{
+			/* Unlike the specification, we don't set the 'delete' arugment to True
+			   since we slurp the INCR's chunks in even-smaller chunks of 4096 bytes. */
+			if ((XGetWindowProperty
+			     (g_display, g_wnd, rdesktop_clipboard_target_atom, offset, 4096L,
+			      False, AnyPropertyType, &type, &format, &nitems, &bytes_left,
+			      &data) != Success))
+			{
+				XFree(data);
+				return;
+			}
+
+			if (nitems == 0)
+			{
+				/* INCR transfer finished */
+				XGetWindowAttributes(g_display, g_wnd, &wa);
+				XSelectInput(g_display, g_wnd,
+					     (wa.your_event_mask ^ PropertyChangeMask));
+				XFree(data);
+				g_waiting_for_INCR = 0;
+
+				if (g_clip_buflen > 0)
+				{
+					if (!xclip_send_data_with_convert
+					    (g_clip_buffer, g_clip_buflen, g_incr_target))
+					{
+						helper_cliprdr_send_empty_response();
+					}
+					xfree(g_clip_buffer);
+					g_clip_buffer = NULL;
+					g_clip_buflen = 0;
+				}
+			}
+			else
+			{
+				/* Another chunk in the INCR transfer */
+				offset += (nitems / 4);	/* offset at which to begin the next slurp */
+				g_clip_buffer = xrealloc(g_clip_buffer, g_clip_buflen + nitems);
+				memcpy(g_clip_buffer + g_clip_buflen, data, nitems);
+				g_clip_buflen += nitems;
+
+				XFree(data);
+			}
+		}
+		XDeleteProperty(g_display, g_wnd, rdesktop_clipboard_target_atom);
+		return;
+	}
+
+	if ((event->atom == rdesktop_selection_notify_atom) &&
+	    (event->window == DefaultRootWindow(g_display)))
+		xclip_probe_selections();
+}
+#endif
+
+
+/* Called when the RDP server announces new clipboard data formats.
+   In response, we:
+   - take ownership over the clipboard
+   - declare those formats in their Windows native form
+     to other rdesktop instances on this X server */
+void
+ui_clip_format_announce(uint8 * data, uint32 length)
+{
+	acquire_time = g_last_gesturetime;
+
+	XSetSelectionOwner(g_display, primary_atom, g_wnd, acquire_time);
+	if (XGetSelectionOwner(g_display, primary_atom) != g_wnd)
+		warning("Failed to aquire ownership of PRIMARY clipboard\n");
+
+	XSetSelectionOwner(g_display, clipboard_atom, g_wnd, acquire_time);
+	if (XGetSelectionOwner(g_display, clipboard_atom) != g_wnd)
+		warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
+
+	if (formats_data)
+		xfree(formats_data);
+	formats_data = xmalloc(length);
+	memcpy(formats_data, data, length);
+	formats_data_length = length;
+
+	xclip_notify_change();
+}
+
+/* Called when the RDP server responds with clipboard data (after we've requested it). */
+void
+ui_clip_handle_data(uint8 * data, uint32 length)
+{
+	RD_BOOL free_data = False;
+
+	if (length == 0)
+	{
+		xclip_refuse_selection(&selection_request);
+		has_selection_request = False;
+		return;
+	}
+
+	if (selection_request.target == format_string_atom || selection_request.target == XA_STRING)
+	{
+		/* We're expecting a CF_TEXT response */
+		uint8 *firstnull;
+
+		/* translate linebreaks */
+		crlf2lf(data, &length);
+
+		/* Only send data up to null byte, if any */
+		firstnull = (uint8 *) strchr((char *) data, '\0');
+		if (firstnull)
+		{
+			length = firstnull - data + 1;
+		}
+	}
+#ifdef USE_UNICODE_CLIPBOARD
+	else if (selection_request.target == format_utf8_string_atom)
+	{
+		/* We're expecting a CF_UNICODETEXT response */
+		iconv_t cd = iconv_open("UTF-8", WINDOWS_CODEPAGE);
+		if (cd != (iconv_t) - 1)
+		{
+			size_t utf8_length = length * 2;
+			char *utf8_data = malloc(utf8_length);
+			size_t utf8_length_remaining = utf8_length;
+			char *utf8_data_remaining = utf8_data;
+			char *data_remaining = (char *) data;
+			size_t length_remaining = (size_t) length;
+			if (utf8_data == NULL)
+			{
+				iconv_close(cd);
+				return;
+			}
+			iconv(cd, (ICONV_CONST char **) &data_remaining, &length_remaining,
+			      &utf8_data_remaining, &utf8_length_remaining);
+			iconv_close(cd);
+			free_data = True;
+			data = (uint8 *) utf8_data;
+			length = utf8_length - utf8_length_remaining;
+			/* translate linebreaks (works just as well on UTF-8) */
+			crlf2lf(data, &length);
+		}
+	}
+	else if (selection_request.target == format_unicode_atom)
+	{
+		/* We're expecting a CF_UNICODETEXT response, so what we're
+		   receiving matches our requirements and there's no need
+		   for further conversions. */
+	}
+#endif
+	else if (selection_request.target == rdesktop_native_atom)
+	{
+		/* Pass as-is */
+	}
+	else
+	{
+		DEBUG_CLIPBOARD(("ui_clip_handle_data: BUG! I don't know how to convert selection target %s!\n", XGetAtomName(g_display, selection_request.target)));
+		xclip_refuse_selection(&selection_request);
+		has_selection_request = False;
+		return;
+	}
+
+	xclip_provide_selection(&selection_request, selection_request.target, 8, data, length - 1);
+	has_selection_request = False;
+
+	if (free_data)
+		free(data);
+}
+
+void
+ui_clip_request_failed()
+{
+	xclip_refuse_selection(&selection_request);
+	has_selection_request = False;
+}
+
+void
+ui_clip_request_data(uint32 format)
+{
+	Window primary_owner, clipboard_owner;
+
+	DEBUG_CLIPBOARD(("Request from server for format %d\n", format));
+	rdp_clipboard_request_format = format;
+
+	if (probing_selections)
+	{
+		DEBUG_CLIPBOARD(("ui_clip_request_data: Selection probe in progress. Cannot handle request.\n"));
+		helper_cliprdr_send_empty_response();
+		return;
+	}
+
+	xclip_clear_target_props();
+
+	if (rdesktop_is_selection_owner)
+	{
+		XChangeProperty(g_display, g_wnd, rdesktop_clipboard_target_atom,
+				XA_INTEGER, 32, PropModeReplace, (unsigned char *) &format, 1);
+
+		XConvertSelection(g_display, primary_atom, rdesktop_native_atom,
+				  rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
+		return;
+	}
+
+	if (auto_mode)
+		primary_owner = XGetSelectionOwner(g_display, primary_atom);
+	else
+		primary_owner = None;
+
+	clipboard_owner = XGetSelectionOwner(g_display, clipboard_atom);
+
+	/* Both available */
+	if ((primary_owner != None) && (clipboard_owner != None))
+	{
+		primary_timestamp = 0;
+		clipboard_timestamp = 0;
+		XConvertSelection(g_display, primary_atom, timestamp_atom,
+				  rdesktop_primary_timestamp_target_atom, g_wnd, CurrentTime);
+		XConvertSelection(g_display, clipboard_atom, timestamp_atom,
+				  rdesktop_clipboard_timestamp_target_atom, g_wnd, CurrentTime);
+		return;
+	}
+
+	/* Just PRIMARY */
+	if (primary_owner != None)
+	{
+		XConvertSelection(g_display, primary_atom, targets_atom,
+				  rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
+		return;
+	}
+
+	/* Just CLIPBOARD */
+	if (clipboard_owner != None)
+	{
+		XConvertSelection(g_display, clipboard_atom, targets_atom,
+				  rdesktop_clipboard_target_atom, g_wnd, CurrentTime);
+		return;
+	}
+
+	/* No data available */
+	helper_cliprdr_send_empty_response();
+}
+
+void
+ui_clip_sync(void)
+{
+	xclip_probe_selections();
+}
+
+void
+ui_clip_set_mode(const char *optarg)
+{
+	g_rdpclip = True;
+
+	if (str_startswith(optarg, "PRIMARYCLIPBOARD"))
+		auto_mode = True;
+	else if (str_startswith(optarg, "CLIPBOARD"))
+		auto_mode = False;
+	else
+	{
+		warning("Invalid clipboard mode '%s'.\n", optarg);
+		g_rdpclip = False;
+	}
+}
+
+void
+xclip_init(void)
+{
+	if (!g_rdpclip)
+		return;
+
+	if (!cliprdr_init())
+		return;
+
+	primary_atom = XInternAtom(g_display, "PRIMARY", False);
+	clipboard_atom = XInternAtom(g_display, "CLIPBOARD", False);
+	targets_atom = XInternAtom(g_display, "TARGETS", False);
+	timestamp_atom = XInternAtom(g_display, "TIMESTAMP", False);
+	rdesktop_clipboard_target_atom =
+		XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TARGET", False);
+	rdesktop_primary_timestamp_target_atom =
+		XInternAtom(g_display, "_RDESKTOP_PRIMARY_TIMESTAMP_TARGET", False);
+	rdesktop_clipboard_timestamp_target_atom =
+		XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_TIMESTAMP_TARGET", False);
+	incr_atom = XInternAtom(g_display, "INCR", False);
+	format_string_atom = XInternAtom(g_display, "STRING", False);
+	format_utf8_string_atom = XInternAtom(g_display, "UTF8_STRING", False);
+	format_unicode_atom = XInternAtom(g_display, "text/unicode", False);
+
+	/* rdesktop sets _RDESKTOP_SELECTION_NOTIFY on the root window when acquiring the clipboard.
+	   Other interested rdesktops can use this to notify their server of the available formats. */
+	rdesktop_selection_notify_atom =
+		XInternAtom(g_display, "_RDESKTOP_SELECTION_NOTIFY", False);
+	XSelectInput(g_display, DefaultRootWindow(g_display), PropertyChangeMask);
+	probing_selections = False;
+
+	rdesktop_native_atom = XInternAtom(g_display, "_RDESKTOP_NATIVE", False);
+	rdesktop_clipboard_formats_atom =
+		XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_FORMATS", False);
+	rdesktop_primary_owner_atom = XInternAtom(g_display, "_RDESKTOP_PRIMARY_OWNER", False);
+	rdesktop_clipboard_owner_atom = XInternAtom(g_display, "_RDESKTOP_CLIPBOARD_OWNER", False);
+
+	num_targets = 0;
+	targets[num_targets++] = targets_atom;
+	targets[num_targets++] = timestamp_atom;
+	targets[num_targets++] = rdesktop_native_atom;
+	targets[num_targets++] = rdesktop_clipboard_formats_atom;
+#ifdef USE_UNICODE_CLIPBOARD
+	targets[num_targets++] = format_utf8_string_atom;
+#endif
+	targets[num_targets++] = format_unicode_atom;
+	targets[num_targets++] = format_string_atom;
+	targets[num_targets++] = XA_STRING;
+}
+
+void
+xclip_deinit(void)
+{
+	if (XGetSelectionOwner(g_display, primary_atom) == g_wnd)
+		XSetSelectionOwner(g_display, primary_atom, None, acquire_time);
+	if (XGetSelectionOwner(g_display, clipboard_atom) == g_wnd)
+		XSetSelectionOwner(g_display, clipboard_atom, None, acquire_time);
+	xclip_notify_change();
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/xkeymap.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/xkeymap.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/xkeymap.c	(revision 55121)
@@ -0,0 +1,1160 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   User interface services - X keyboard mapping
+
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright 2003-2008 Peter Astrand <astrand@cendio.se> for Cendio AB
+   Copyright 2014 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifdef RDP2VNC
+#include "vnc/x11stubs.h"
+#else
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#endif
+
+#include <ctype.h>
+#include <limits.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include "rdesktop.h"
+#include "scancodes.h"
+
+#define KEYMAP_SIZE 0x7f+1
+#define KEYMAP_MASK 0x7f
+#define KEYMAP_MAX_LINE_LENGTH 80
+
+extern Display *g_display;
+extern Window g_wnd;
+extern char g_keymapname[16];
+extern unsigned int g_keylayout;
+extern int g_keyboard_type;
+extern int g_keyboard_subtype;
+extern int g_keyboard_functionkeys;
+extern int g_win_button_size;
+extern RD_BOOL g_enable_compose;
+extern RDP_VERSION g_rdp_version;
+extern RD_BOOL g_numlock_sync;
+
+static RD_BOOL keymap_loaded;
+static key_translation_entry *keymap[KEYMAP_SIZE];
+static KeySym keypress_keysyms[256];
+static int min_keycode;
+static uint16 remote_modifier_state = 0;
+static uint16 saved_remote_modifier_state = 0;
+
+static void update_modifier_state(uint8 scancode, RD_BOOL pressed);
+
+/* Free key_translation structure, including linked list */
+static void
+free_key_translation(key_translation * ptr)
+{
+	key_translation *next;
+
+	while (ptr)
+	{
+		next = ptr->next;
+		xfree(ptr);
+		ptr = next;
+	}
+}
+
+/* Free the key_translation_entry for a given keysym and remove from the table */
+static void
+delete_key_translation_entry(KeySym keysym)
+{
+	uint32 hash;
+	key_translation_entry *ptr;
+	key_translation_entry *next;
+	key_translation_entry *prev;
+	key_translation_entry tmp;
+
+	/* Faking a prev node allows us to keep the algorithm simple */
+	hash = keysym & KEYMAP_MASK;
+	ptr = keymap[hash];
+	tmp.next = ptr;
+	prev = &tmp;
+
+	while (ptr)
+	{
+		next = ptr->next;
+		if (ptr->keysym == keysym)
+		{
+			free_key_translation(ptr->tr);
+			prev->next = next;
+			xfree(ptr);
+		}
+		else
+		{
+			prev = ptr;
+		}
+
+		ptr = next;
+	}
+
+	/* Copy pointer back from our fake node */
+	keymap[hash] = tmp.next;
+}
+
+/* Allocate and return a new entry in the translation table */
+static key_translation_entry *
+new_key_translation_entry(KeySym keysym)
+{
+	uint32 hash;
+	key_translation_entry *entry;
+
+	/* Clear out any existing entry */
+	delete_key_translation_entry(keysym);
+
+	/* Allocate the new one */
+	entry = (key_translation_entry *) xmalloc(sizeof(key_translation_entry));
+	memset(entry, 0, sizeof(key_translation_entry));
+	entry->keysym = keysym;
+
+	/* And insert it at head of list */
+	hash = keysym & KEYMAP_MASK;
+	entry->next = keymap[hash];
+	keymap[hash] = entry;
+
+	return entry;
+}
+
+/* Retrieve the key_translation_entry for a given keysym */
+static key_translation_entry *
+get_key_translation_entry(uint32 keysym)
+{
+	key_translation_entry *ptr;
+	key_translation_entry *next;
+
+	ptr = keymap[keysym & KEYMAP_MASK];
+
+	while (ptr)
+	{
+		next = ptr->next;
+		if (ptr->keysym == keysym)
+			return ptr;
+
+		ptr = next;
+	}
+
+	/* Not found */
+	return NULL;
+}
+
+static void
+add_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname)
+{
+	KeySym keysym;
+	key_translation_entry *entry;
+
+	keysym = XStringToKeysym(keyname);
+	if (keysym == NoSymbol)
+	{
+		DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring)\n", keyname, mapname));
+		return;
+	}
+
+	DEBUG_KBD(("Adding translation, keysym=0x%x, scancode=0x%x, "
+		   "modifiers=0x%x\n", (unsigned int) keysym, scancode, modifiers));
+
+	/* Make a new entry in the table */
+	entry = new_key_translation_entry(keysym);
+
+	/* And add the new translation to it */
+	entry->tr = (key_translation *) xmalloc(sizeof(key_translation));
+	memset(entry->tr, 0, sizeof(key_translation));
+	entry->tr->scancode = scancode;
+	entry->tr->modifiers = modifiers;
+
+	return;
+}
+
+static void
+add_sequence(char *rest, char *mapname)
+{
+	KeySym keysym;
+	KeySym seq_keysym;
+	key_translation_entry *entry;
+	key_translation *tr, **prev_next;
+	size_t chars;
+	char keyname[KEYMAP_MAX_LINE_LENGTH];
+
+	/* Skip over whitespace after the sequence keyword */
+	chars = strspn(rest, " \t");
+	rest += chars;
+
+	/* Fetch the keysym name */
+	chars = strcspn(rest, " \t\0");
+	STRNCPY(keyname, rest, chars + 1);
+	rest += chars;
+
+	keysym = XStringToKeysym(keyname);
+	if (keysym == NoSymbol)
+	{
+		DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname, mapname));
+		return;
+	}
+
+	DEBUG_KBD(("Adding sequence for keysym (0x%lx, %s) -> ", keysym, keyname));
+
+	entry = new_key_translation_entry(keysym);
+	prev_next = &(entry->tr);
+
+	while (*rest)
+	{
+		/* Skip whitespace */
+		chars = strspn(rest, " \t");
+		rest += chars;
+
+		/* Fetch the keysym name */
+		chars = strcspn(rest, " \t\0");
+		STRNCPY(keyname, rest, chars + 1);
+		rest += chars;
+
+		/* Handle trailing whitespace */
+		if (*keyname == 0)
+			break;
+
+		seq_keysym = XStringToKeysym(keyname);
+		if (seq_keysym == NoSymbol)
+		{
+			DEBUG_KBD(("Bad keysym \"%s\" in keymap %s (ignoring line)\n", keyname,
+				   mapname));
+			delete_key_translation_entry(keysym);
+			return;
+		}
+
+		/* Allocate space for key_translation structure */
+		tr = (key_translation *) xmalloc(sizeof(key_translation));
+		memset(tr, 0, sizeof(key_translation));
+
+		/* Do this straight away so the key_translation won't get orphaned on error */
+		if (!entry->tr)
+			entry->tr = tr;
+
+		*prev_next = tr;
+		prev_next = &tr->next;
+		tr->seq_keysym = seq_keysym;
+
+		DEBUG_KBD(("0x%x, ", (unsigned int) seq_keysym));
+	}
+	DEBUG_KBD(("\n"));
+}
+
+RD_BOOL
+xkeymap_from_locale(const char *locale)
+{
+	char *str, *ptr;
+	FILE *fp;
+
+	/* Create a working copy */
+	str = xstrdup(locale);
+
+	/* Truncate at dot and at */
+	ptr = strrchr(str, '.');
+	if (ptr)
+		*ptr = '\0';
+	ptr = strrchr(str, '@');
+	if (ptr)
+		*ptr = '\0';
+
+	/* Replace _ with - */
+	ptr = strrchr(str, '_');
+	if (ptr)
+		*ptr = '-';
+
+	/* Convert to lowercase */
+	ptr = str;
+	while (*ptr)
+	{
+		*ptr = tolower((int) *ptr);
+		ptr++;
+	}
+
+	/* Try to open this keymap (da-dk) */
+	fp = xkeymap_open(str);
+	if (fp == NULL)
+	{
+		/* Truncate at dash */
+		ptr = strrchr(str, '-');
+		if (ptr)
+			*ptr = '\0';
+
+		/* Try the short name (da) */
+		fp = xkeymap_open(str);
+	}
+
+	if (fp)
+	{
+		fclose(fp);
+		STRNCPY(g_keymapname, str, sizeof(g_keymapname));
+		xfree(str);
+		return True;
+	}
+
+	xfree(str);
+	return False;
+}
+
+
+/* Joins two path components. The result should be freed with
+   xfree(). */
+static char *
+pathjoin(const char *a, const char *b)
+{
+	char *result;
+	result = xmalloc(PATH_MAX * 2 + 1);
+
+	if (b[0] == '/')
+	{
+		strncpy(result, b, PATH_MAX);
+	}
+	else
+	{
+		strncpy(result, a, PATH_MAX);
+		strcat(result, "/");
+		strncat(result, b, PATH_MAX);
+	}
+	return result;
+}
+
+/* Try to open a keymap with fopen() */
+FILE *
+xkeymap_open(const char *filename)
+{
+	char *path1, *path2;
+	char *home;
+	FILE *fp;
+
+	/* Try ~/.rdesktop/keymaps */
+	home = getenv("HOME");
+	if (home)
+	{
+		path1 = pathjoin(home, ".rdesktop/keymaps");
+		path2 = pathjoin(path1, filename);
+		xfree(path1);
+		fp = fopen(path2, "r");
+		xfree(path2);
+		if (fp)
+			return fp;
+	}
+
+	/* Try KEYMAP_PATH */
+	path1 = pathjoin(KEYMAP_PATH, filename);
+	fp = fopen(path1, "r");
+	xfree(path1);
+	if (fp)
+		return fp;
+
+	/* Try current directory, in case we are running from the source
+	   tree */
+	path1 = pathjoin("keymaps", filename);
+	fp = fopen(path1, "r");
+	xfree(path1);
+	if (fp)
+		return fp;
+
+	return NULL;
+}
+
+static RD_BOOL
+xkeymap_read(char *mapname)
+{
+	FILE *fp;
+	char line[KEYMAP_MAX_LINE_LENGTH];
+	unsigned int line_num = 0;
+	unsigned int line_length = 0;
+	char *keyname, *p;
+	char *line_rest;
+	uint8 scancode;
+	uint16 modifiers;
+
+	fp = xkeymap_open(mapname);
+	if (fp == NULL)
+	{
+		error("Failed to open keymap %s\n", mapname);
+		return False;
+	}
+
+	/* FIXME: More tolerant on white space */
+	while (fgets(line, sizeof(line), fp) != NULL)
+	{
+		line_num++;
+
+		/* Replace the \n with \0 */
+		p = strchr(line, '\n');
+		if (p != NULL)
+			*p = 0;
+
+		line_length = strlen(line);
+
+		/* Completely empty line */
+		if (strspn(line, " \t\n\r\f\v") == line_length)
+		{
+			continue;
+		}
+
+		/* Include */
+		if (str_startswith(line, "include "))
+		{
+			if (!xkeymap_read(line + sizeof("include ") - 1))
+				return False;
+			continue;
+		}
+
+		/* map */
+		if (str_startswith(line, "map "))
+		{
+			g_keylayout = strtoul(line + sizeof("map ") - 1, NULL, 16);
+			DEBUG_KBD(("Keylayout 0x%x\n", g_keylayout));
+			continue;
+		}
+
+		/* compose */
+		if (str_startswith(line, "enable_compose"))
+		{
+			DEBUG_KBD(("Enabling compose handling\n"));
+			g_enable_compose = True;
+			continue;
+		}
+
+		/* sequence */
+		if (str_startswith(line, "sequence"))
+		{
+			add_sequence(line + sizeof("sequence") - 1, mapname);
+			continue;
+		}
+
+		/* keyboard_type */
+		if (str_startswith(line, "keyboard_type "))
+		{
+			g_keyboard_type = strtol(line + sizeof("keyboard_type ") - 1, NULL, 16);
+			DEBUG_KBD(("keyboard_type 0x%x\n", g_keyboard_type));
+			continue;
+		}
+
+		/* keyboard_subtype */
+		if (str_startswith(line, "keyboard_subtype "))
+		{
+			g_keyboard_subtype =
+				strtol(line + sizeof("keyboard_subtype ") - 1, NULL, 16);
+			DEBUG_KBD(("keyboard_subtype 0x%x\n", g_keyboard_subtype));
+			continue;
+		}
+
+		/* keyboard_functionkeys */
+		if (str_startswith(line, "keyboard_functionkeys "))
+		{
+			g_keyboard_functionkeys =
+				strtol(line + sizeof("keyboard_functionkeys ") - 1, NULL, 16);
+			DEBUG_KBD(("keyboard_functionkeys 0x%x\n", g_keyboard_functionkeys));
+			continue;
+		}
+
+		/* Comment */
+		if (line[0] == '#')
+		{
+			continue;
+		}
+
+		/* Normal line */
+		keyname = line;
+		p = strchr(line, ' ');
+		if (p == NULL)
+		{
+			error("Bad line %d in keymap %s\n", line_num, mapname);
+			continue;
+		}
+		else
+		{
+			*p = 0;
+		}
+
+		/* scancode */
+		p++;
+		scancode = strtol(p, &line_rest, 16);
+
+		/* flags */
+		/* FIXME: Should allow case-insensitive flag names. 
+		   Fix by using lex+yacc... */
+		modifiers = 0;
+		if (strstr(line_rest, "altgr"))
+		{
+			MASK_ADD_BITS(modifiers, MapAltGrMask);
+		}
+
+		if (strstr(line_rest, "shift"))
+		{
+			MASK_ADD_BITS(modifiers, MapLeftShiftMask);
+		}
+
+		if (strstr(line_rest, "numlock"))
+		{
+			MASK_ADD_BITS(modifiers, MapNumLockMask);
+		}
+
+		if (strstr(line_rest, "localstate"))
+		{
+			MASK_ADD_BITS(modifiers, MapLocalStateMask);
+		}
+
+		if (strstr(line_rest, "inhibit"))
+		{
+			MASK_ADD_BITS(modifiers, MapInhibitMask);
+		}
+
+		add_to_keymap(keyname, scancode, modifiers, mapname);
+
+		if (strstr(line_rest, "addupper"))
+		{
+			/* Automatically add uppercase key, with same modifiers 
+			   plus shift */
+			for (p = keyname; *p; p++)
+				*p = toupper((int) *p);
+			MASK_ADD_BITS(modifiers, MapLeftShiftMask);
+			add_to_keymap(keyname, scancode, modifiers, mapname);
+		}
+	}
+
+	fclose(fp);
+	return True;
+}
+
+
+/* Before connecting and creating UI */
+void
+xkeymap_init(void)
+{
+	unsigned int max_keycode;
+
+	if (strcmp(g_keymapname, "none"))
+	{
+		if (xkeymap_read(g_keymapname))
+			keymap_loaded = True;
+	}
+
+	XDisplayKeycodes(g_display, &min_keycode, (int *) &max_keycode);
+}
+
+static void
+send_winkey(uint32 ev_time, RD_BOOL pressed, RD_BOOL leftkey)
+{
+	uint8 winkey;
+
+	if (leftkey)
+		winkey = SCANCODE_CHAR_LWIN;
+	else
+		winkey = SCANCODE_CHAR_RWIN;
+
+	if (pressed)
+	{
+		if (g_rdp_version >= RDP_V5)
+		{
+			rdp_send_scancode(ev_time, RDP_KEYPRESS, winkey);
+		}
+		else
+		{
+			/* RDP4 doesn't support winkey. Fake with Ctrl-Esc */
+			rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL);
+			rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC);
+		}
+	}
+	else
+	{
+		/* key released */
+		if (g_rdp_version >= RDP_V5)
+		{
+			rdp_send_scancode(ev_time, RDP_KEYRELEASE, winkey);
+		}
+		else
+		{
+			rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC);
+			rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
+		}
+	}
+}
+
+static void
+reset_winkey(uint32 ev_time)
+{
+	if (g_rdp_version >= RDP_V5)
+	{
+		/* For some reason, it seems to suffice to release
+		 *either* the left or right winkey. */
+		rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LWIN);
+	}
+}
+
+
+void
+set_keypress_keysym(unsigned int keycode, KeySym keysym)
+{
+	if (keycode < 8 || keycode > 255)
+		return;
+	keypress_keysyms[keycode] = keysym;
+}
+
+
+KeySym
+reset_keypress_keysym(unsigned int keycode, KeySym keysym)
+{
+	KeySym ks;
+	if (keycode < 8 || keycode > 255)
+		return keysym;
+	ks = keypress_keysyms[keycode];
+	if (ks != 0)
+	{
+		keypress_keysyms[keycode] = 0;
+	}
+	else
+	{
+		ks = keysym;
+	}
+
+	return ks;
+}
+
+
+/* Handle special key combinations */
+RD_BOOL
+handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, RD_BOOL pressed)
+{
+	switch (keysym)
+	{
+		case XK_Return:
+			if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))
+			    && (get_key_state(state, XK_Control_L)
+				|| get_key_state(state, XK_Control_R)))
+			{
+				/* Ctrl-Alt-Enter: toggle full screen */
+				if (pressed)
+					xwin_toggle_fullscreen();
+				return True;
+			}
+			break;
+
+		case XK_Break:
+			/* Send Break sequence E0 46 E0 C6 */
+			if (pressed)
+			{
+				rdp_send_scancode(ev_time, RDP_KEYPRESS,
+						  (SCANCODE_EXTENDED | 0x46));
+				rdp_send_scancode(ev_time, RDP_KEYPRESS,
+						  (SCANCODE_EXTENDED | 0xc6));
+			}
+			/* No release sequence */
+			return True;
+			break;
+
+		case XK_Pause:
+			/* According to MS Keyboard Scan Code
+			   Specification, pressing Pause should result
+			   in E1 1D 45 E1 9D C5. I'm not exactly sure
+			   of how this is supposed to be sent via
+			   RDP. The code below seems to work, but with
+			   the side effect that Left Ctrl stays
+			   down. Therefore, we release it when Pause
+			   is released. */
+			if (pressed)
+			{
+				rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
+				rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
+				rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0);
+				rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0);
+				rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0);
+				rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0);
+			}
+			else
+			{
+				/* Release Left Ctrl */
+				rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE,
+					       0x1d, 0);
+			}
+			return True;
+			break;
+
+		case XK_Meta_L:	/* Windows keys */
+		case XK_Super_L:
+		case XK_Hyper_L:
+			send_winkey(ev_time, pressed, True);
+			return True;
+			break;
+
+		case XK_Meta_R:
+		case XK_Super_R:
+		case XK_Hyper_R:
+			send_winkey(ev_time, pressed, False);
+			return True;
+			break;
+
+		case XK_space:
+			/* Prevent access to the Windows system menu in single app mode */
+			if (g_win_button_size
+			    && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)))
+				return True;
+			break;
+
+		case XK_Num_Lock:
+			/* Synchronize on key release */
+			if (g_numlock_sync && !pressed)
+				rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
+					       ui_get_numlock_state(read_keyboard_state()), 0);
+
+			/* Inhibit */
+			return True;
+			break;
+		case XK_Overlay1_Enable:
+			/* Toggle SeamlessRDP */
+			if (pressed)
+				ui_seamless_toggle();
+			break;
+
+	}
+	return False;
+}
+
+
+key_translation
+xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state)
+{
+	key_translation tr = { 0, 0, 0, 0 };
+	key_translation *ptr;
+	key_translation_entry *entry;
+
+	entry = get_key_translation_entry(keysym);
+	ptr = entry ? entry->tr : NULL;
+
+	if (ptr)
+	{
+		tr = *ptr;
+		if (tr.seq_keysym == 0)	/* Normal scancode translation */
+		{
+			if (MASK_HAS_BITS(tr.modifiers, MapInhibitMask))
+			{
+				DEBUG_KBD(("Inhibiting key\n"));
+				tr.scancode = 0;
+				return tr;
+			}
+
+			if (MASK_HAS_BITS(tr.modifiers, MapLocalStateMask))
+			{
+				/* The modifiers to send for this key should be obtained
+				   from the local state. Currently, only shift is implemented. */
+				if (MASK_HAS_BITS(state, ShiftMask))
+				{
+					tr.modifiers = MapLeftShiftMask;
+				}
+			}
+
+			/* Windows interprets CapsLock+Ctrl+key
+			   differently from Shift+Ctrl+key. Since we
+			   are simulating CapsLock with Shifts, things
+			   like Ctrl+f with CapsLock on breaks. To
+			   solve this, we are releasing Shift if Ctrl
+			   is on, but only if Shift isn't physically pressed. */
+			if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
+			    && MASK_HAS_BITS(remote_modifier_state, MapCtrlMask)
+			    && !MASK_HAS_BITS(state, ShiftMask))
+			{
+				DEBUG_KBD(("Non-physical Shift + Ctrl pressed, releasing Shift\n"));
+				MASK_REMOVE_BITS(tr.modifiers, MapShiftMask);
+			}
+
+			DEBUG_KBD(("Found scancode translation, scancode=0x%x, modifiers=0x%x\n",
+				   tr.scancode, tr.modifiers));
+		}
+	}
+	else
+	{
+		if (keymap_loaded)
+			warning("No translation for (keysym 0x%lx, %s)\n", keysym,
+				get_ksname(keysym));
+
+		/* not in keymap, try to interpret the raw scancode */
+		if (((int) keycode >= min_keycode) && (keycode <= 0x60))
+		{
+			tr.scancode = keycode - min_keycode;
+
+			/* The modifiers to send for this key should be
+			   obtained from the local state. Currently, only
+			   shift is implemented. */
+			if (MASK_HAS_BITS(state, ShiftMask))
+			{
+				tr.modifiers = MapLeftShiftMask;
+			}
+
+			DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode));
+		}
+		else
+		{
+			DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode));
+		}
+	}
+
+	return tr;
+}
+
+static RD_BOOL
+is_modifier(uint8 scancode)
+{
+	switch (scancode)
+	{
+		case SCANCODE_CHAR_LSHIFT:
+		case SCANCODE_CHAR_RSHIFT:
+		case SCANCODE_CHAR_LCTRL:
+		case SCANCODE_CHAR_RCTRL:
+		case SCANCODE_CHAR_LALT:
+		case SCANCODE_CHAR_RALT:
+		case SCANCODE_CHAR_LWIN:
+		case SCANCODE_CHAR_RWIN:
+		case SCANCODE_CHAR_NUMLOCK:
+			return True;
+		default:
+			break;
+	}
+	return False;
+}
+
+
+void
+xkeymap_send_keys(uint32 keysym, unsigned int keycode, unsigned int state, uint32 ev_time,
+		  RD_BOOL pressed, uint8 nesting)
+{
+	key_translation tr, *ptr;
+	tr = xkeymap_translate_key(keysym, keycode, state);
+
+	if (tr.seq_keysym == 0)
+	{
+		/* Scancode translation */
+		if (tr.scancode == 0)
+			return;
+
+		save_remote_modifiers(tr.scancode);
+		ensure_remote_modifiers(ev_time, tr);
+		rdp_send_scancode(ev_time, pressed ? RDP_KEYPRESS : RDP_KEYRELEASE, tr.scancode);
+		restore_remote_modifiers(ev_time, tr.scancode);
+		return;
+	}
+
+	/* Sequence, only on key down */
+	if (pressed)
+	{
+		ptr = &tr;
+		do
+		{
+			DEBUG_KBD(("Handling sequence element, keysym=0x%x\n",
+				   (unsigned int) ptr->seq_keysym));
+
+			if (nesting++ > 32)
+			{
+				error("Sequence nesting too deep\n");
+				return;
+			}
+
+			xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, True, nesting);
+			xkeymap_send_keys(ptr->seq_keysym, keycode, state, ev_time, False, nesting);
+			ptr = ptr->next;
+		}
+		while (ptr);
+	}
+}
+
+uint16
+xkeymap_translate_button(unsigned int button)
+{
+	switch (button)
+	{
+		case Button1:	/* left */
+			return MOUSE_FLAG_BUTTON1;
+		case Button2:	/* middle */
+			return MOUSE_FLAG_BUTTON3;
+		case Button3:	/* right */
+			return MOUSE_FLAG_BUTTON2;
+		case Button4:	/* wheel up */
+			return MOUSE_FLAG_BUTTON4;
+		case Button5:	/* wheel down */
+			return MOUSE_FLAG_BUTTON5;
+	}
+
+	return 0;
+}
+
+char *
+get_ksname(uint32 keysym)
+{
+	char *ksname = NULL;
+
+	if (keysym == NoSymbol)
+		ksname = "NoSymbol";
+	else if (!(ksname = XKeysymToString(keysym)))
+		ksname = "(no name)";
+
+	return ksname;
+}
+
+void
+save_remote_modifiers(uint8 scancode)
+{
+	if (is_modifier(scancode))
+		return;
+
+	saved_remote_modifier_state = remote_modifier_state;
+}
+
+void
+restore_remote_modifiers(uint32 ev_time, uint8 scancode)
+{
+	key_translation dummy = { };
+
+	if (is_modifier(scancode))
+		return;
+
+	dummy.scancode = 0;
+	dummy.modifiers = saved_remote_modifier_state;
+	ensure_remote_modifiers(ev_time, dummy);
+}
+
+void
+ensure_remote_modifiers(uint32 ev_time, key_translation tr)
+{
+	/* If this key is a modifier, do nothing */
+	if (is_modifier(tr.scancode))
+		return;
+
+	if (!g_numlock_sync)
+	{
+		/* NumLock */
+		if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)
+		    != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask))
+		{
+			/* The remote modifier state is not correct */
+			uint16 new_remote_state;
+
+			if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask))
+			{
+				DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n"));
+				new_remote_state = KBD_FLAG_NUMLOCK;
+				remote_modifier_state = MapNumLockMask;
+			}
+			else
+			{
+				DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n"));
+				new_remote_state = 0;
+				remote_modifier_state = 0;
+			}
+
+			rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0);
+		}
+	}
+
+
+	/* Shift. Left shift and right shift are treated as equal; either is fine. */
+	if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)
+	    != MASK_HAS_BITS(remote_modifier_state, MapShiftMask))
+	{
+		/* The remote modifier state is not correct */
+		if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask))
+		{
+			/* Needs left shift. Send down. */
+			rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT);
+		}
+		else if (MASK_HAS_BITS(tr.modifiers, MapRightShiftMask))
+		{
+			/* Needs right shift. Send down. */
+			rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RSHIFT);
+		}
+		else
+		{
+			/* Should not use this modifier. Send up for shift currently pressed. */
+			if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask))
+				/* Left shift is down */
+				rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
+			else
+				/* Right shift is down */
+				rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
+		}
+	}
+
+	/* AltGr */
+	if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask)
+	    != MASK_HAS_BITS(remote_modifier_state, MapAltGrMask))
+	{
+		/* The remote modifier state is not correct */
+		if (MASK_HAS_BITS(tr.modifiers, MapAltGrMask))
+		{
+			/* Needs this modifier. Send down. */
+			rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RALT);
+		}
+		else
+		{
+			/* Should not use this modifier. Send up. */
+			rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
+		}
+	}
+
+
+}
+
+
+unsigned int
+read_keyboard_state()
+{
+#ifdef RDP2VNC
+	return 0;
+#else
+	unsigned int state;
+	Window wdummy;
+	int dummy;
+
+	XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
+	return state;
+#endif
+}
+
+
+uint16
+ui_get_numlock_state(unsigned int state)
+{
+	uint16 numlock_state = 0;
+
+	if (get_key_state(state, XK_Num_Lock))
+		numlock_state = KBD_FLAG_NUMLOCK;
+
+	return numlock_state;
+}
+
+
+void
+reset_modifier_keys()
+{
+	unsigned int state = read_keyboard_state();
+
+	/* reset keys */
+	uint32 ev_time;
+	ev_time = time(NULL);
+
+	if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)
+	    && !get_key_state(state, XK_Shift_L))
+		rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT);
+
+	if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)
+	    && !get_key_state(state, XK_Shift_R))
+		rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT);
+
+	if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask)
+	    && !get_key_state(state, XK_Control_L))
+		rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL);
+
+	if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask)
+	    && !get_key_state(state, XK_Control_R))
+		rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL);
+
+	if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L))
+		rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT);
+
+	if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) &&
+	    !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch)
+	    && !get_key_state(state, XK_ISO_Level3_Shift))
+		rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT);
+
+	reset_winkey(ev_time);
+
+	if (g_numlock_sync)
+		rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0);
+}
+
+
+static void
+update_modifier_state(uint8 scancode, RD_BOOL pressed)
+{
+#ifdef WITH_DEBUG_KBD
+	uint16 old_modifier_state;
+
+	old_modifier_state = remote_modifier_state;
+#endif
+
+	switch (scancode)
+	{
+		case SCANCODE_CHAR_LSHIFT:
+			MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed);
+			break;
+		case SCANCODE_CHAR_RSHIFT:
+			MASK_CHANGE_BIT(remote_modifier_state, MapRightShiftMask, pressed);
+			break;
+		case SCANCODE_CHAR_LCTRL:
+			MASK_CHANGE_BIT(remote_modifier_state, MapLeftCtrlMask, pressed);
+			break;
+		case SCANCODE_CHAR_RCTRL:
+			MASK_CHANGE_BIT(remote_modifier_state, MapRightCtrlMask, pressed);
+			break;
+		case SCANCODE_CHAR_LALT:
+			MASK_CHANGE_BIT(remote_modifier_state, MapLeftAltMask, pressed);
+			break;
+		case SCANCODE_CHAR_RALT:
+			MASK_CHANGE_BIT(remote_modifier_state, MapRightAltMask, pressed);
+			break;
+		case SCANCODE_CHAR_LWIN:
+			MASK_CHANGE_BIT(remote_modifier_state, MapLeftWinMask, pressed);
+			break;
+		case SCANCODE_CHAR_RWIN:
+			MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed);
+			break;
+		case SCANCODE_CHAR_NUMLOCK:
+			/* KeyReleases for NumLocks are sent immediately. Toggle the
+			   modifier state only on Keypress */
+			if (pressed && !g_numlock_sync)
+			{
+				RD_BOOL newNumLockState;
+				newNumLockState =
+					(MASK_HAS_BITS
+					 (remote_modifier_state, MapNumLockMask) == False);
+				MASK_CHANGE_BIT(remote_modifier_state,
+						MapNumLockMask, newNumLockState);
+			}
+	}
+
+#ifdef WITH_DEBUG_KBD
+	if (old_modifier_state != remote_modifier_state)
+	{
+		DEBUG_KBD(("Before updating modifier_state:0x%x, pressed=0x%x\n",
+			   old_modifier_state, pressed));
+		DEBUG_KBD(("After updating modifier_state:0x%x\n", remote_modifier_state));
+	}
+#endif
+
+}
+
+/* Send keyboard input */
+void
+rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode)
+{
+	update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));
+
+	if (scancode & SCANCODE_EXTENDED)
+	{
+		DEBUG_KBD(("Sending extended scancode=0x%x, flags=0x%x\n",
+			   scancode & ~SCANCODE_EXTENDED, flags));
+		rdp_send_input(time, RDP_INPUT_SCANCODE, flags | KBD_FLAG_EXT,
+			       scancode & ~SCANCODE_EXTENDED, 0);
+	}
+	else
+	{
+		DEBUG_KBD(("Sending scancode=0x%x, flags=0x%x\n", scancode, flags));
+		rdp_send_input(time, RDP_INPUT_SCANCODE, flags, scancode, 0);
+	}
+}
Index: /trunk/src/VBox/RDP/client-1.8.3/xproto.h
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/xproto.h	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/xproto.h	(revision 55121)
@@ -0,0 +1,17 @@
+void xclip_handle_SelectionNotify(XSelectionEvent * event);
+void xclip_handle_SelectionRequest(XSelectionRequestEvent * xevent);
+void xclip_handle_SelectionClear(void);
+void xclip_handle_PropertyNotify(XPropertyEvent * xev);
+int ewmh_get_window_state(Window w);
+int ewmh_change_state(Window wnd, int state);
+int ewmh_move_to_desktop(Window wnd, unsigned int desktop);
+int ewmh_get_window_desktop(Window wnd);
+void ewmh_set_wm_name(Window wnd, const char *title);
+int ewmh_set_window_popup(Window wnd);
+int ewmh_set_window_modal(Window wnd);
+void ewmh_set_icon(Window wnd, int width, int height, const char *rgba_data);
+void ewmh_del_icon(Window wnd, int width, int height);
+int ewmh_set_window_above(Window wnd);
+RD_BOOL ewmh_is_window_above(Window w);
+void set_keypress_keysym(unsigned int keycode, KeySym keysym);
+KeySym reset_keypress_keysym(unsigned int keycode, KeySym keysym);
Index: /trunk/src/VBox/RDP/client-1.8.3/xwin.c
===================================================================
--- /trunk/src/VBox/RDP/client-1.8.3/xwin.c	(revision 55121)
+++ /trunk/src/VBox/RDP/client-1.8.3/xwin.c	(revision 55121)
@@ -0,0 +1,4400 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   User interface services - X Window System
+   Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
+   Copyright 2007-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
+   Copyright 2002-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
+   Copyright 2012-2013 Henrik Andersson <hean01@cendio.se> for Cendio AB
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xproto.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+#include <strings.h>
+#include "rdesktop.h"
+#include "xproto.h"
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+
+extern int g_sizeopt;
+extern int g_width;
+extern int g_height;
+extern int g_xpos;
+extern int g_ypos;
+extern int g_pos;
+extern RD_BOOL g_sendmotion;
+extern RD_BOOL g_fullscreen;
+extern RD_BOOL g_grab_keyboard;
+extern RD_BOOL g_hide_decorations;
+extern RD_BOOL g_pending_resize;
+extern char g_title[];
+extern char g_seamless_spawn_cmd[];
+/* Color depth of the RDP session.
+   As of RDP 5.1, it may be 8, 15, 16 or 24. */
+extern int g_server_depth;
+extern int g_win_button_size;
+
+Display *g_display;
+Time g_last_gesturetime;
+static int g_x_socket;
+static Screen *g_screen;
+Window g_wnd;
+
+/* SeamlessRDP support */
+typedef struct _seamless_group
+{
+	Window wnd;
+	unsigned long id;
+	unsigned int refcnt;
+} seamless_group;
+typedef struct _seamless_window
+{
+	Window wnd;
+	unsigned long id;
+	unsigned long behind;
+	seamless_group *group;
+	int xoffset, yoffset;
+	int width, height;
+	int state;		/* normal/minimized/maximized. */
+	unsigned int desktop;
+	struct timeval *position_timer;
+
+	RD_BOOL outstanding_position;
+	unsigned int outpos_serial;
+	int outpos_xoffset, outpos_yoffset;
+	int outpos_width, outpos_height;
+
+	unsigned int icon_size;
+	unsigned int icon_offset;
+	char icon_buffer[32 * 32 * 4];
+
+	struct _seamless_window *next;
+} seamless_window;
+static seamless_window *g_seamless_windows = NULL;
+static unsigned long g_seamless_focused = 0;
+static RD_BOOL g_seamless_started = False;	/* Server end is up and running */
+static RD_BOOL g_seamless_active = False;	/* We are currently in seamless mode */
+static RD_BOOL g_seamless_hidden = False;	/* Desktop is hidden on server */
+static RD_BOOL g_seamless_broken_restack = False;	/* WM does not properly restack */
+extern RD_BOOL g_seamless_rdp;
+extern RD_BOOL g_seamless_persistent_mode;
+
+extern uint32 g_embed_wnd;
+RD_BOOL g_enable_compose = False;
+RD_BOOL g_Unobscured;		/* used for screenblt */
+static GC g_gc = NULL;
+static GC g_create_bitmap_gc = NULL;
+static GC g_create_glyph_gc = NULL;
+static XRectangle g_clip_rectangle;
+static Visual *g_visual;
+/* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
+   This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
+   as far as we're concerned. */
+static int g_depth;
+/* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
+   This may be larger than g_depth, in which case some of the bits would
+   be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
+static int g_bpp;
+static XIM g_IM;
+static XIC g_IC;
+static XModifierKeymap *g_mod_map;
+/* Maps logical (xmodmap -pp) pointing device buttons (0-based) back
+   to physical (1-based) indices. */
+static unsigned char g_pointer_log_to_phys_map[32];
+static Cursor g_current_cursor;
+static RD_HCURSOR g_null_cursor = NULL;
+static Atom g_protocol_atom, g_kill_atom;
+extern Atom g_net_wm_state_atom;
+extern Atom g_net_wm_desktop_atom;
+static RD_BOOL g_focused;
+static RD_BOOL g_mouse_in_wnd;
+/* Indicates that:
+   1) visual has 15, 16 or 24 depth and the same color channel masks
+      as its RDP equivalent (implies X server is LE),
+   2) host is LE
+   This will trigger an optimization whose real value is questionable.
+*/
+static RD_BOOL g_compatible_arch;
+/* Indicates whether RDP's bitmaps and our XImages have the same
+   binary format. If so, we can avoid an expensive translation.
+   Note that this can be true when g_compatible_arch is false,
+   e.g.:
+   
+     RDP(LE) <-> host(BE) <-> X-Server(LE)
+     
+   ('host' is the machine running rdesktop; the host simply memcpy's
+    so its endianess doesn't matter)
+ */
+static RD_BOOL g_no_translate_image = False;
+
+/* endianness */
+static RD_BOOL g_host_be;
+static RD_BOOL g_xserver_be;
+static int g_red_shift_r, g_blue_shift_r, g_green_shift_r;
+static int g_red_shift_l, g_blue_shift_l, g_green_shift_l;
+
+/* software backing store */
+extern RD_BOOL g_ownbackstore;
+static Pixmap g_backstore = 0;
+
+/* Moving in single app mode */
+static RD_BOOL g_moving_wnd;
+static int g_move_x_offset = 0;
+static int g_move_y_offset = 0;
+static RD_BOOL g_using_full_workarea = False;
+
+#ifdef WITH_RDPSND
+extern RD_BOOL g_rdpsnd;
+#endif
+
+/* MWM decorations */
+#define MWM_HINTS_DECORATIONS   (1L << 1)
+#define PROP_MOTIF_WM_HINTS_ELEMENTS    5
+typedef struct
+{
+	unsigned long flags;
+	unsigned long functions;
+	unsigned long decorations;
+	long inputMode;
+	unsigned long status;
+}
+PropMotifWmHints;
+
+typedef struct
+{
+	uint32 red;
+	uint32 green;
+	uint32 blue;
+}
+PixelColour;
+
+#define ON_ALL_SEAMLESS_WINDOWS(func, args) \
+        do { \
+                seamless_window *sw; \
+                XRectangle rect; \
+		if (!g_seamless_windows) break; \
+                for (sw = g_seamless_windows; sw; sw = sw->next) { \
+                    rect.x = g_clip_rectangle.x - sw->xoffset; \
+                    rect.y = g_clip_rectangle.y - sw->yoffset; \
+                    rect.width = g_clip_rectangle.width; \
+                    rect.height = g_clip_rectangle.height; \
+                    XSetClipRectangles(g_display, g_gc, 0, 0, &rect, 1, YXBanded); \
+                    func args; \
+                } \
+                XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded); \
+        } while (0)
+
+static void
+seamless_XFillPolygon(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
+{
+	points[0].x -= xoffset;
+	points[0].y -= yoffset;
+	XFillPolygon(g_display, d, g_gc, points, npoints, Complex, CoordModePrevious);
+	points[0].x += xoffset;
+	points[0].y += yoffset;
+}
+
+static void
+seamless_XDrawLines(Drawable d, XPoint * points, int npoints, int xoffset, int yoffset)
+{
+	points[0].x -= xoffset;
+	points[0].y -= yoffset;
+	XDrawLines(g_display, d, g_gc, points, npoints, CoordModePrevious);
+	points[0].x += xoffset;
+	points[0].y += yoffset;
+}
+
+#define FILL_RECTANGLE(x,y,cx,cy)\
+{ \
+	XFillRectangle(g_display, g_wnd, g_gc, x, y, cx, cy); \
+        ON_ALL_SEAMLESS_WINDOWS(XFillRectangle, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy)); \
+	if (g_ownbackstore) \
+		XFillRectangle(g_display, g_backstore, g_gc, x, y, cx, cy); \
+}
+
+#define FILL_RECTANGLE_BACKSTORE(x,y,cx,cy)\
+{ \
+	XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
+}
+
+#define FILL_POLYGON(p,np)\
+{ \
+	XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
+	if (g_ownbackstore) \
+		XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
+	ON_ALL_SEAMLESS_WINDOWS(seamless_XFillPolygon, (sw->wnd, p, np, sw->xoffset, sw->yoffset)); \
+}
+
+#define DRAW_ELLIPSE(x,y,cx,cy,m)\
+{ \
+	switch (m) \
+	{ \
+		case 0:	/* Outline */ \
+			XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
+                        ON_ALL_SEAMLESS_WINDOWS(XDrawArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
+			if (g_ownbackstore) \
+				XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
+			break; \
+		case 1: /* Filled */ \
+			XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
+			ON_ALL_SEAMLESS_WINDOWS(XFillArc, (g_display, sw->wnd, g_gc, x-sw->xoffset, y-sw->yoffset, cx, cy, 0, 360*64)); \
+			if (g_ownbackstore) \
+				XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
+			break; \
+	} \
+}
+
+/* colour maps */
+extern RD_BOOL g_owncolmap;
+static Colormap g_xcolmap;
+static uint32 *g_colmap = NULL;
+
+#define TRANSLATE(col)		( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
+#define SET_FOREGROUND(col)	XSetForeground(g_display, g_gc, TRANSLATE(col));
+#define SET_BACKGROUND(col)	XSetBackground(g_display, g_gc, TRANSLATE(col));
+
+static int rop2_map[] = {
+	GXclear,		/* 0 */
+	GXnor,			/* DPon */
+	GXandInverted,		/* DPna */
+	GXcopyInverted,		/* Pn */
+	GXandReverse,		/* PDna */
+	GXinvert,		/* Dn */
+	GXxor,			/* DPx */
+	GXnand,			/* DPan */
+	GXand,			/* DPa */
+	GXequiv,		/* DPxn */
+	GXnoop,			/* D */
+	GXorInverted,		/* DPno */
+	GXcopy,			/* P */
+	GXorReverse,		/* PDno */
+	GXor,			/* DPo */
+	GXset			/* 1 */
+};
+
+#define SET_FUNCTION(rop2)	{ if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, rop2_map[rop2]); }
+#define RESET_FUNCTION(rop2)	{ if (rop2 != ROP2_COPY) XSetFunction(g_display, g_gc, GXcopy); }
+
+static seamless_window *
+sw_get_window_by_id(unsigned long id)
+{
+	seamless_window *sw;
+	for (sw = g_seamless_windows; sw; sw = sw->next)
+	{
+		if (sw->id == id)
+			return sw;
+	}
+	return NULL;
+}
+
+
+static seamless_window *
+sw_get_window_by_wnd(Window wnd)
+{
+	seamless_window *sw;
+	for (sw = g_seamless_windows; sw; sw = sw->next)
+	{
+		if (sw->wnd == wnd)
+			return sw;
+	}
+	return NULL;
+}
+
+
+static void
+sw_remove_window(seamless_window * win)
+{
+	seamless_window *sw, **prevnext = &g_seamless_windows;
+	for (sw = g_seamless_windows; sw; sw = sw->next)
+	{
+		if (sw == win)
+		{
+			*prevnext = sw->next;
+			sw->group->refcnt--;
+			if (sw->group->refcnt == 0)
+			{
+				XDestroyWindow(g_display, sw->group->wnd);
+				xfree(sw->group);
+			}
+			xfree(sw->position_timer);
+			xfree(sw);
+			return;
+		}
+		prevnext = &sw->next;
+	}
+	return;
+}
+
+
+/* Move all windows except wnd to new desktop */
+static void
+sw_all_to_desktop(Window wnd, unsigned int desktop)
+{
+	seamless_window *sw;
+	for (sw = g_seamless_windows; sw; sw = sw->next)
+	{
+		if (sw->wnd == wnd)
+			continue;
+		if (sw->desktop != desktop)
+		{
+			ewmh_move_to_desktop(sw->wnd, desktop);
+			sw->desktop = desktop;
+		}
+	}
+}
+
+
+/* Send our position */
+static void
+sw_update_position(seamless_window * sw)
+{
+	XWindowAttributes wa;
+	int x, y;
+	Window child_return;
+	unsigned int serial;
+
+	XGetWindowAttributes(g_display, sw->wnd, &wa);
+	XTranslateCoordinates(g_display, sw->wnd, wa.root,
+			      -wa.border_width, -wa.border_width, &x, &y, &child_return);
+
+	serial = seamless_send_position(sw->id, x, y, wa.width, wa.height, 0);
+
+	sw->outstanding_position = True;
+	sw->outpos_serial = serial;
+
+	sw->outpos_xoffset = x;
+	sw->outpos_yoffset = y;
+	sw->outpos_width = wa.width;
+	sw->outpos_height = wa.height;
+}
+
+
+/* Check if it's time to send our position */
+static void
+sw_check_timers()
+{
+	seamless_window *sw;
+	struct timeval now;
+
+	gettimeofday(&now, NULL);
+	for (sw = g_seamless_windows; sw; sw = sw->next)
+	{
+		if (timerisset(sw->position_timer) && timercmp(sw->position_timer, &now, <))
+		{
+			timerclear(sw->position_timer);
+			sw_update_position(sw);
+		}
+	}
+}
+
+
+static void
+sw_restack_window(seamless_window * sw, unsigned long behind)
+{
+	seamless_window *sw_above;
+
+	/* Remove window from stack */
+	for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
+	{
+		if (sw_above->behind == sw->id)
+			break;
+	}
+
+	if (sw_above)
+		sw_above->behind = sw->behind;
+
+	/* And then add it at the new position */
+	for (sw_above = g_seamless_windows; sw_above; sw_above = sw_above->next)
+	{
+		if (sw_above->behind == behind)
+			break;
+	}
+
+	if (sw_above)
+		sw_above->behind = sw->id;
+
+	sw->behind = behind;
+}
+
+
+static void
+sw_handle_restack(seamless_window * sw)
+{
+	Status status;
+	Window root, parent, *children;
+	unsigned int nchildren, i;
+	seamless_window *sw_below;
+
+	status = XQueryTree(g_display, RootWindowOfScreen(g_screen),
+			    &root, &parent, &children, &nchildren);
+	if (!status || !nchildren)
+		return;
+
+	sw_below = NULL;
+
+	i = 0;
+	while (children[i] != sw->wnd)
+	{
+		i++;
+		if (i >= nchildren)
+			goto end;
+	}
+
+	for (i++; i < nchildren; i++)
+	{
+		sw_below = sw_get_window_by_wnd(children[i]);
+		if (sw_below)
+			break;
+	}
+
+	if (!sw_below && !sw->behind)
+		goto end;
+	if (sw_below && (sw_below->id == sw->behind))
+		goto end;
+
+	if (sw_below)
+	{
+		seamless_send_zchange(sw->id, sw_below->id, 0);
+		sw_restack_window(sw, sw_below->id);
+	}
+	else
+	{
+		seamless_send_zchange(sw->id, 0, 0);
+		sw_restack_window(sw, 0);
+	}
+
+      end:
+	XFree(children);
+}
+
+
+static seamless_group *
+sw_find_group(unsigned long id, RD_BOOL dont_create)
+{
+	seamless_window *sw;
+	seamless_group *sg;
+	XSetWindowAttributes attribs;
+
+	for (sw = g_seamless_windows; sw; sw = sw->next)
+	{
+		if (sw->group->id == id)
+			return sw->group;
+	}
+
+	if (dont_create)
+		return NULL;
+
+	sg = xmalloc(sizeof(seamless_group));
+
+	sg->wnd =
+		XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0,
+			      CopyFromParent, CopyFromParent, CopyFromParent, 0, &attribs);
+
+	sg->id = id;
+	sg->refcnt = 0;
+
+	return sg;
+}
+
+
+static void
+mwm_hide_decorations(Window wnd)
+{
+	PropMotifWmHints motif_hints;
+	Atom hintsatom;
+
+	/* setup the property */
+	motif_hints.flags = MWM_HINTS_DECORATIONS;
+	motif_hints.decorations = 0;
+
+	/* get the atom for the property */
+	hintsatom = XInternAtom(g_display, "_MOTIF_WM_HINTS", False);
+	if (!hintsatom)
+	{
+		warning("Failed to get atom _MOTIF_WM_HINTS: probably your window manager does not support MWM hints\n");
+		return;
+	}
+
+	XChangeProperty(g_display, wnd, hintsatom, hintsatom, 32, PropModeReplace,
+			(unsigned char *) &motif_hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
+
+}
+
+typedef struct _sw_configurenotify_context
+{
+	Window window;
+	unsigned long serial;
+} sw_configurenotify_context;
+
+/* Predicate procedure for sw_wait_configurenotify */
+static Bool
+sw_configurenotify_p(Display * display, XEvent * xevent, XPointer arg)
+{
+	sw_configurenotify_context *context = (sw_configurenotify_context *) arg;
+	if (xevent->xany.type == ConfigureNotify
+	    && xevent->xconfigure.window == context->window
+	    && xevent->xany.serial >= context->serial)
+		return True;
+
+	return False;
+}
+
+/* Wait for a ConfigureNotify, with a equal or larger serial, on the
+   specified window. The event will be removed from the queue. We
+   could use XMaskEvent(StructureNotifyMask), but we would then risk
+   throwing away crucial events like DestroyNotify. 
+
+   After a ConfigureWindow, according to ICCCM section 4.1.5, we
+   should recieve a ConfigureNotify, either a real or synthetic
+   one. This indicates that the configure has been "completed".
+   However, some WMs such as several versions of Metacity fails to
+   send synthetic events. See bug
+   http://bugzilla.gnome.org/show_bug.cgi?id=322840. We need to use a
+   timeout to avoid a hang. Tk uses the same approach. */
+static void
+sw_wait_configurenotify(Window wnd, unsigned long serial)
+{
+	XEvent xevent;
+	sw_configurenotify_context context;
+	struct timeval now;
+	struct timeval future;
+	RD_BOOL got = False;
+
+	context.window = wnd;
+	context.serial = serial;
+
+	gettimeofday(&future, NULL);
+	future.tv_usec += 500000;
+
+	do
+	{
+		if (XCheckIfEvent(g_display, &xevent, sw_configurenotify_p, (XPointer) & context))
+		{
+			got = True;
+			break;
+		}
+		usleep(100000);
+		gettimeofday(&now, NULL);
+	}
+	while (timercmp(&now, &future, <));
+
+	if (!got)
+	{
+		warning("Broken Window Manager: Timeout while waiting for ConfigureNotify\n");
+	}
+}
+
+/* Get the toplevel window, in case of reparenting */
+static Window
+sw_get_toplevel(Window wnd)
+{
+	Window root, parent;
+	Window *child_list;
+	unsigned int num_children;
+
+	while (1)
+	{
+		XQueryTree(g_display, wnd, &root, &parent, &child_list, &num_children);
+		if (root == parent)
+		{
+			break;
+		}
+		else if (!parent)
+		{
+			warning("Internal error: sw_get_toplevel called with root window\n");
+		}
+
+		wnd = parent;
+	}
+
+	return wnd;
+}
+
+
+/* Check if wnd is already behind a window wrt stacking order */
+static RD_BOOL
+sw_window_is_behind(Window wnd, Window behind)
+{
+	Window dummy1, dummy2;
+	Window *child_list;
+	unsigned int num_children;
+	unsigned int i;
+	RD_BOOL found_behind = False;
+	RD_BOOL found_wnd = False;
+
+	wnd = sw_get_toplevel(wnd);
+	behind = sw_get_toplevel(behind);
+
+	XQueryTree(g_display, RootWindowOfScreen(g_screen), &dummy1, &dummy2, &child_list,
+		   &num_children);
+
+	for (i = num_children - 1; i >= 0; i--)
+	{
+		if (child_list[i] == behind)
+		{
+			found_behind = True;
+		}
+		else if (child_list[i] == wnd)
+		{
+			found_wnd = True;
+			break;
+		}
+	}
+
+	if (child_list)
+		XFree(child_list);
+
+	if (!found_wnd)
+	{
+		warning("sw_window_is_behind: Unable to find window 0x%lx\n", wnd);
+
+		if (!found_behind)
+		{
+			warning("sw_window_is_behind: Unable to find behind window 0x%lx\n",
+				behind);
+		}
+	}
+
+	return found_behind;
+}
+
+
+/* Test if the window manager correctly handles window restacking. In
+   particular, we are testing if it's possible to place a window
+   between two other windows. Many WMs such as Metacity can only stack
+   windows on the top or bottom. The window creation should mostly
+   match ui_seamless_create_window. */
+static void
+seamless_restack_test()
+{
+	/* The goal is to have the middle window between top and
+	   bottom.  The middle window is initially at the top,
+	   though. */
+	Window wnds[3];		/* top, middle and bottom */
+	int i;
+	XEvent xevent;
+	XWindowChanges values;
+	unsigned long restack_serial;
+
+	for (i = 0; i < 3; i++)
+	{
+		char name[64];
+		wnds[i] =
+			XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen), 0, 0, 20, 20,
+					    0, 0, 0);
+		snprintf(name, sizeof(name), "SeamlessRDP restack test - window %d", i);
+		XStoreName(g_display, wnds[i], name);
+		ewmh_set_wm_name(wnds[i], name);
+
+		/* Hide decorations. Often this means that no
+		   reparenting will be done, which makes the restack
+		   easier. Besides, we want to mimic our other
+		   seamless windows as much as possible. We must still
+		   handle the case with reparenting, though. */
+		mwm_hide_decorations(wnds[i]);
+
+		/* Prevent windows from appearing in task bar */
+		XSetTransientForHint(g_display, wnds[i], RootWindowOfScreen(g_screen));
+		ewmh_set_window_popup(wnds[i]);
+
+		/* We need to catch MapNotify/ConfigureNotify */
+		XSelectInput(g_display, wnds[i], StructureNotifyMask);
+	}
+
+	/* Map Windows. Currently, we assume that XMapRaised places
+	   the window on the top of the stack. Should be fairly safe;
+	   the window is configured before it's mapped. */
+	XMapRaised(g_display, wnds[2]);	/* bottom */
+	do
+	{
+		XWindowEvent(g_display, wnds[2], StructureNotifyMask, &xevent);
+	}
+	while (xevent.type != MapNotify);
+	XMapRaised(g_display, wnds[0]);	/* top */
+	do
+	{
+		XWindowEvent(g_display, wnds[0], StructureNotifyMask, &xevent);
+	}
+	while (xevent.type != MapNotify);
+	XMapRaised(g_display, wnds[1]);	/* middle */
+	do
+	{
+		XWindowEvent(g_display, wnds[1], StructureNotifyMask, &xevent);
+	}
+	while (xevent.type != MapNotify);
+
+	/* The stacking order should now be 1 - 0 - 2 */
+	if (!sw_window_is_behind(wnds[0], wnds[1]) || !sw_window_is_behind(wnds[2], wnds[1]))
+	{
+		/* Ok, technically a WM is allowed to stack windows arbitrarily, but... */
+		warning("Broken Window Manager: Unable to test window restacking\n");
+		g_seamless_broken_restack = True;
+		for (i = 0; i < 3; i++)
+			XDestroyWindow(g_display, wnds[i]);
+		return;
+	}
+
+	/* Restack, using XReconfigureWMWindow, which should correctly
+	   handle reparented windows as well as nonreparenting WMs. */
+	values.stack_mode = Below;
+	values.sibling = wnds[0];
+	restack_serial = XNextRequest(g_display);
+	XReconfigureWMWindow(g_display, wnds[1], DefaultScreen(g_display), CWStackMode | CWSibling,
+			     &values);
+	sw_wait_configurenotify(wnds[1], restack_serial);
+
+	/* Now verify that middle is behind top but not behind
+	   bottom */
+	if (!sw_window_is_behind(wnds[1], wnds[0]))
+	{
+		warning("Broken Window Manager: doesn't handle restack (restack request was ignored)\n");
+		g_seamless_broken_restack = True;
+	}
+	else if (sw_window_is_behind(wnds[1], wnds[2]))
+	{
+		warning("Broken Window Manager: doesn't handle restack (window was moved to bottom)\n");
+		g_seamless_broken_restack = True;
+	}
+
+	/* Destroy windows */
+	for (i = 0; i < 3; i++)
+	{
+		XDestroyWindow(g_display, wnds[i]);
+		do
+		{
+			XWindowEvent(g_display, wnds[i], StructureNotifyMask, &xevent);
+		}
+		while (xevent.type != DestroyNotify);
+	}
+}
+
+#define SPLITCOLOUR15(colour, rv) \
+{ \
+	rv.red = ((colour >> 7) & 0xf8) | ((colour >> 12) & 0x7); \
+	rv.green = ((colour >> 2) & 0xf8) | ((colour >> 8) & 0x7); \
+	rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
+}
+
+#define SPLITCOLOUR16(colour, rv) \
+{ \
+	rv.red = ((colour >> 8) & 0xf8) | ((colour >> 13) & 0x7); \
+	rv.green = ((colour >> 3) & 0xfc) | ((colour >> 9) & 0x3); \
+	rv.blue = ((colour << 3) & 0xf8) | ((colour >> 2) & 0x7); \
+} \
+
+#define SPLITCOLOUR24(colour, rv) \
+{ \
+	rv.blue = (colour & 0xff0000) >> 16; \
+	rv.green = (colour & 0x00ff00) >> 8; \
+	rv.red = (colour & 0x0000ff); \
+}
+
+#define MAKECOLOUR(pc) \
+	((pc.red >> g_red_shift_r) << g_red_shift_l) \
+		| ((pc.green >> g_green_shift_r) << g_green_shift_l) \
+		| ((pc.blue >> g_blue_shift_r) << g_blue_shift_l) \
+
+#define BSWAP16(x) { x = (((x & 0xff) << 8) | (x >> 8)); }
+#define BSWAP24(x) { x = (((x & 0xff) << 16) | (x >> 16) | (x & 0xff00)); }
+#define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
+			x = (x << 16) | (x >> 16); }
+
+/* The following macros output the same octet sequences
+   on both BE and LE hosts: */
+
+#define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
+#define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
+#define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
+#define LOUT16(o, x) { *(o++) = x; *(o++) = x >> 8; }
+#define LOUT24(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; }
+#define LOUT32(o, x) { *(o++) = x; *(o++) = x >> 8; *(o++) = x >> 16; *(o++) = x >> 24; }
+
+static uint32
+translate_colour(uint32 colour)
+{
+	PixelColour pc;
+	switch (g_server_depth)
+	{
+		case 15:
+			SPLITCOLOUR15(colour, pc);
+			break;
+		case 16:
+			SPLITCOLOUR16(colour, pc);
+			break;
+		case 24:
+		case 32:
+			SPLITCOLOUR24(colour, pc);
+			break;
+		default:
+			/* Avoid warning */
+			pc.red = 0;
+			pc.green = 0;
+			pc.blue = 0;
+			break;
+	}
+	return MAKECOLOUR(pc);
+}
+
+/* indent is confused by UNROLL8 */
+/* *INDENT-OFF* */
+
+/* repeat and unroll, similar to bitmap.c */
+/* potentialy any of the following translate */
+/* functions can use repeat but just doing */
+/* the most common ones */
+
+#define UNROLL8(stm) { stm stm stm stm stm stm stm stm }
+/* 2 byte output repeat */
+#define REPEAT2(stm) \
+{ \
+	while (out <= end - 8 * 2) \
+		UNROLL8(stm) \
+	while (out < end) \
+		{ stm } \
+}
+/* 3 byte output repeat */
+#define REPEAT3(stm) \
+{ \
+	while (out <= end - 8 * 3) \
+		UNROLL8(stm) \
+	while (out < end) \
+		{ stm } \
+}
+/* 4 byte output repeat */
+#define REPEAT4(stm) \
+{ \
+	while (out <= end - 8 * 4) \
+		UNROLL8(stm) \
+	while (out < end) \
+		{ stm } \
+}
+/* *INDENT-ON* */
+
+static void
+translate8to8(const uint8 * data, uint8 * out, uint8 * end)
+{
+	while (out < end)
+		*(out++) = (uint8) g_colmap[*(data++)];
+}
+
+static void
+translate8to16(const uint8 * data, uint8 * out, uint8 * end)
+{
+	uint16 value;
+
+	if (g_compatible_arch)
+	{
+		/* *INDENT-OFF* */
+		REPEAT2
+		(
+			*((uint16 *) out) = g_colmap[*(data++)];
+			out += 2;
+		)
+		/* *INDENT-ON* */
+	}
+	else if (g_xserver_be)
+	{
+		while (out < end)
+		{
+			value = (uint16) g_colmap[*(data++)];
+			BOUT16(out, value);
+		}
+	}
+	else
+	{
+		while (out < end)
+		{
+			value = (uint16) g_colmap[*(data++)];
+			LOUT16(out, value);
+		}
+	}
+}
+
+/* little endian - conversion happens when colourmap is built */
+static void
+translate8to24(const uint8 * data, uint8 * out, uint8 * end)
+{
+	uint32 value;
+
+	if (g_compatible_arch)
+	{
+		while (out < end)
+		{
+			value = g_colmap[*(data++)];
+			BOUT24(out, value);
+		}
+	}
+	else
+	{
+		while (out < end)
+		{
+			value = g_colmap[*(data++)];
+			LOUT24(out, value);
+		}
+	}
+}
+
+static void
+translate8to32(const uint8 * data, uint8 * out, uint8 * end)
+{
+	uint32 value;
+
+	if (g_compatible_arch)
+	{
+		/* *INDENT-OFF* */
+		REPEAT4
+		(
+			*((uint32 *) out) = g_colmap[*(data++)];
+			out += 4;
+		)
+		/* *INDENT-ON* */
+	}
+	else if (g_xserver_be)
+	{
+		while (out < end)
+		{
+			value = g_colmap[*(data++)];
+			BOUT32(out, value);
+		}
+	}
+	else
+	{
+		while (out < end)
+		{
+			value = g_colmap[*(data++)];
+			LOUT32(out, value);
+		}
+	}
+}
+
+static void
+translate15to16(const uint16 * data, uint8 * out, uint8 * end)
+{
+	uint16 pixel;
+	uint16 value;
+	PixelColour pc;
+
+	if (g_xserver_be)
+	{
+		while (out < end)
+		{
+			pixel = *(data++);
+			if (g_host_be)
+			{
+				BSWAP16(pixel);
+			}
+			SPLITCOLOUR15(pixel, pc);
+			value = MAKECOLOUR(pc);
+			BOUT16(out, value);
+		}
+	}
+	else
+	{
+		while (out < end)
+		{
+			pixel = *(data++);
+			if (g_host_be)
+			{
+				BSWAP16(pixel);
+			}
+			SPLITCOLOUR15(pixel, pc);
+			value = MAKECOLOUR(pc);
+			LOUT16(out, value);
+		}
+	}
+}
+
+static void
+translate15to24(const uint16 * data, uint8 * out, uint8 * end)
+{
+	uint32 value;
+	uint16 pixel;
+	PixelColour pc;
+
+	if (g_compatible_arch)
+	{
+		/* *INDENT-OFF* */
+		REPEAT3
+		(
+			pixel = *(data++);
+			SPLITCOLOUR15(pixel, pc);
+			*(out++) = pc.blue;
+			*(out++) = pc.green;
+			*(out++) = pc.red;
+		)
+		/* *INDENT-ON* */
+	}
+	else if (g_xserver_be)
+	{
+		while (out < end)
+		{
+			pixel = *(data++);
+			if (g_host_be)
+			{
+				BSWAP16(pixel);
+			}
+			SPLITCOLOUR15(pixel, pc);
+			value = MAKECOLOUR(pc);
+			BOUT24(out, value);
+		}
+	}
+	else
+	{
+		while (out < end)
+		{
+			pixel = *(data++);
+			if (g_host_be)
+			{
+				BSWAP16(pixel);
+			}
+			SPLITCOLOUR15(pixel, pc);
+			value = MAKECOLOUR(pc);
+			LOUT24(out, value);
+		}
+	}
+}
+
+static void
+translate15to32(const uint16 * data, uint8 * out, uint8 * end)
+{
+	uint16 pixel;
+	uint32 value;
+	PixelColour pc;
+
+	if (g_compatible_arch)
+	{
+		/* *INDENT-OFF* */
+		REPEAT4
+		(
+			pixel = *(data++);
+			SPLITCOLOUR15(pixel, pc);
+			*(out++) = pc.blue;
+			*(out++) = pc.green;
+			*(out++) = pc.red;
+			*(out++) = 0;
+		)
+		/* *INDENT-ON* */
+	}
+	else if (g_xserver_be)
+	{
+		while (out < end)
+		{
+			pixel = *(data++);
+			if (g_host_be)
+			{
+				BSWAP16(pixel);
+			}
+			SPLITCOLOUR15(pixel, pc);
+			value = MAKECOLOUR(pc);
+			BOUT32(out, value);
+		}
+	}
+	else
+	{
+		while (out < end)
+		{
+			pixel = *(data++);
+			if (g_host_be)
+			{
+				BSWAP16(pixel);
+			}
+			SPLITCOLOUR15(pixel, pc);
+			value = MAKECOLOUR(pc);
+			LOUT32(out, value);
+		}
+	}
+}
+
+static void
+translate16to16(const uint16 * data, uint8 * out, uint8 * end)
+{
+	uint16 pixel;
+	uint16 value;
+	PixelColour pc;
+
+	if (g_xserver_be)
+	{
+		if (g_host_be)
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				BSWAP16(pixel);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				BOUT16(out, value);
+			}
+		}
+		else
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				BOUT16(out, value);
+			}
+		}
+	}
+	else
+	{
+		if (g_host_be)
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				BSWAP16(pixel);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				LOUT16(out, value);
+			}
+		}
+		else
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				LOUT16(out, value);
+			}
+		}
+	}
+}
+
+static void
+translate16to24(const uint16 * data, uint8 * out, uint8 * end)
+{
+	uint32 value;
+	uint16 pixel;
+	PixelColour pc;
+
+	if (g_compatible_arch)
+	{
+		/* *INDENT-OFF* */
+		REPEAT3
+		(
+			pixel = *(data++);
+			SPLITCOLOUR16(pixel, pc);
+			*(out++) = pc.blue;
+			*(out++) = pc.green;
+			*(out++) = pc.red;
+		)
+		/* *INDENT-ON* */
+	}
+	else if (g_xserver_be)
+	{
+		if (g_host_be)
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				BSWAP16(pixel);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				BOUT24(out, value);
+			}
+		}
+		else
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				BOUT24(out, value);
+			}
+		}
+	}
+	else
+	{
+		if (g_host_be)
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				BSWAP16(pixel);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				LOUT24(out, value);
+			}
+		}
+		else
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				LOUT24(out, value);
+			}
+		}
+	}
+}
+
+static void
+translate16to32(const uint16 * data, uint8 * out, uint8 * end)
+{
+	uint16 pixel;
+	uint32 value;
+	PixelColour pc;
+
+	if (g_compatible_arch)
+	{
+		/* *INDENT-OFF* */
+		REPEAT4
+		(
+			pixel = *(data++);
+			SPLITCOLOUR16(pixel, pc);
+			*(out++) = pc.blue;
+			*(out++) = pc.green;
+			*(out++) = pc.red;
+			*(out++) = 0;
+		)
+		/* *INDENT-ON* */
+	}
+	else if (g_xserver_be)
+	{
+		if (g_host_be)
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				BSWAP16(pixel);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				BOUT32(out, value);
+			}
+		}
+		else
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				BOUT32(out, value);
+			}
+		}
+	}
+	else
+	{
+		if (g_host_be)
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				BSWAP16(pixel);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				LOUT32(out, value);
+			}
+		}
+		else
+		{
+			while (out < end)
+			{
+				pixel = *(data++);
+				SPLITCOLOUR16(pixel, pc);
+				value = MAKECOLOUR(pc);
+				LOUT32(out, value);
+			}
+		}
+	}
+}
+
+static void
+translate24to16(const uint8 * data, uint8 * out, uint8 * end)
+{
+	uint32 pixel = 0;
+	uint16 value;
+	PixelColour pc;
+
+	while (out < end)
+	{
+		pixel = *(data++) << 16;
+		pixel |= *(data++) << 8;
+		pixel |= *(data++);
+		SPLITCOLOUR24(pixel, pc);
+		value = MAKECOLOUR(pc);
+		if (g_xserver_be)
+		{
+			BOUT16(out, value);
+		}
+		else
+		{
+			LOUT16(out, value);
+		}
+	}
+}
+
+static void
+translate24to24(const uint8 * data, uint8 * out, uint8 * end)
+{
+	uint32 pixel;
+	uint32 value;
+	PixelColour pc;
+
+	if (g_xserver_be)
+	{
+		while (out < end)
+		{
+			pixel = *(data++) << 16;
+			pixel |= *(data++) << 8;
+			pixel |= *(data++);
+			SPLITCOLOUR24(pixel, pc);
+			value = MAKECOLOUR(pc);
+			BOUT24(out, value);
+		}
+	}
+	else
+	{
+		while (out < end)
+		{
+			pixel = *(data++) << 16;
+			pixel |= *(data++) << 8;
+			pixel |= *(data++);
+			SPLITCOLOUR24(pixel, pc);
+			value = MAKECOLOUR(pc);
+			LOUT24(out, value);
+		}
+	}
+}
+
+static void
+translate24to32(const uint8 * data, uint8 * out, uint8 * end)
+{
+	uint32 pixel;
+	uint32 value;
+	PixelColour pc;
+
+	if (g_compatible_arch)
+	{
+		/* *INDENT-OFF* */
+#ifdef NEED_ALIGN
+		REPEAT4
+		(
+			*(out++) = *(data++);
+			*(out++) = *(data++);
+			*(out++) = *(data++);
+			*(out++) = 0;
+		)
+#else
+		REPEAT4
+		(
+		 /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
+		 *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
+		 out += 4;
+		 data += 3;
+		)
+#endif
+		/* *INDENT-ON* */
+	}
+	else if (g_xserver_be)
+	{
+		while (out < end)
+		{
+			pixel = *(data++) << 16;
+			pixel |= *(data++) << 8;
+			pixel |= *(data++);
+			SPLITCOLOUR24(pixel, pc);
+			value = MAKECOLOUR(pc);
+			BOUT32(out, value);
+		}
+	}
+	else
+	{
+		while (out < end)
+		{
+			pixel = *(data++) << 16;
+			pixel |= *(data++) << 8;
+			pixel |= *(data++);
+			SPLITCOLOUR24(pixel, pc);
+			value = MAKECOLOUR(pc);
+			LOUT32(out, value);
+		}
+	}
+}
+
+static uint8 *
+translate_image(int width, int height, uint8 * data)
+{
+	int size;
+	uint8 *out;
+	uint8 *end;
+
+	/*
+	   If RDP depth and X Visual depths match,
+	   and arch(endian) matches, no need to translate:
+	   just return data.
+	   Note: select_visual should've already ensured g_no_translate
+	   is only set for compatible depths, but the RDP depth might've
+	   changed during connection negotiations.
+	 */
+
+	/* todo */
+	if (g_server_depth == 32 && g_depth == 24)
+	{
+		return data;
+	}
+
+	if (g_no_translate_image)
+	{
+		if ((g_depth == 15 && g_server_depth == 15) ||
+		    (g_depth == 16 && g_server_depth == 16) ||
+		    (g_depth == 24 && g_server_depth == 24))
+			return data;
+	}
+
+	size = width * height * (g_bpp / 8);
+	out = (uint8 *) xmalloc(size);
+	end = out + size;
+
+	switch (g_server_depth)
+	{
+		case 24:
+			switch (g_bpp)
+			{
+				case 32:
+					translate24to32(data, out, end);
+					break;
+				case 24:
+					translate24to24(data, out, end);
+					break;
+				case 16:
+					translate24to16(data, out, end);
+					break;
+			}
+			break;
+		case 16:
+			switch (g_bpp)
+			{
+				case 32:
+					translate16to32((uint16 *) data, out, end);
+					break;
+				case 24:
+					translate16to24((uint16 *) data, out, end);
+					break;
+				case 16:
+					translate16to16((uint16 *) data, out, end);
+					break;
+			}
+			break;
+		case 15:
+			switch (g_bpp)
+			{
+				case 32:
+					translate15to32((uint16 *) data, out, end);
+					break;
+				case 24:
+					translate15to24((uint16 *) data, out, end);
+					break;
+				case 16:
+					translate15to16((uint16 *) data, out, end);
+					break;
+			}
+			break;
+		case 8:
+			switch (g_bpp)
+			{
+				case 8:
+					translate8to8(data, out, end);
+					break;
+				case 16:
+					translate8to16(data, out, end);
+					break;
+				case 24:
+					translate8to24(data, out, end);
+					break;
+				case 32:
+					translate8to32(data, out, end);
+					break;
+			}
+			break;
+	}
+	return out;
+}
+
+static void
+xwin_refresh_pointer_map(void)
+{
+	unsigned char phys_to_log_map[sizeof(g_pointer_log_to_phys_map)];
+	int i, pointer_buttons;
+
+	pointer_buttons = XGetPointerMapping(g_display, phys_to_log_map, sizeof(phys_to_log_map));
+	if (pointer_buttons > sizeof(phys_to_log_map))
+		pointer_buttons = sizeof(phys_to_log_map);
+
+	/* if multiple physical buttons map to the same logical button, then
+	 * use the lower numbered physical one */
+	for (i = pointer_buttons - 1; i >= 0; i--)
+	{
+		/* a user could specify arbitrary values for the logical button
+		 * number, ignore any that are abnormally large */
+		if (phys_to_log_map[i] > sizeof(g_pointer_log_to_phys_map))
+			continue;
+		g_pointer_log_to_phys_map[phys_to_log_map[i] - 1] = i + 1;
+	}
+}
+
+RD_BOOL
+get_key_state(unsigned int state, uint32 keysym)
+{
+	int modifierpos, key, keysymMask = 0;
+	int offset;
+
+	KeyCode keycode = XKeysymToKeycode(g_display, keysym);
+
+	if (keycode == NoSymbol)
+		return False;
+
+	for (modifierpos = 0; modifierpos < 8; modifierpos++)
+	{
+		offset = g_mod_map->max_keypermod * modifierpos;
+
+		for (key = 0; key < g_mod_map->max_keypermod; key++)
+		{
+			if (g_mod_map->modifiermap[offset + key] == keycode)
+				keysymMask |= 1 << modifierpos;
+		}
+	}
+
+	return (state & keysymMask) ? True : False;
+}
+
+static void
+calculate_shifts(uint32 mask, int *shift_r, int *shift_l)
+{
+	*shift_l = ffs(mask) - 1;
+	mask >>= *shift_l;
+	*shift_r = 8 - ffs(mask & ~(mask >> 1));
+}
+
+/* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
+   calculates the bits-per-pixel of this channel (a.k.a. colour weight).
+ */
+static unsigned
+calculate_mask_weight(uint32 mask)
+{
+	unsigned weight = 0;
+	do
+	{
+		weight += (mask & 1);
+	}
+	while (mask >>= 1);
+	return weight;
+}
+
+static RD_BOOL
+select_visual(int screen_num)
+{
+	XPixmapFormatValues *pfm;
+	int pixmap_formats_count, visuals_count;
+	XVisualInfo *vmatches = NULL;
+	XVisualInfo template;
+	int i;
+	unsigned red_weight, blue_weight, green_weight;
+
+	red_weight = blue_weight = green_weight = 0;
+
+	if (g_server_depth == -1)
+	{
+		g_server_depth = DisplayPlanes(g_display, DefaultScreen(g_display));
+	}
+
+	pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
+	if (pfm == NULL)
+	{
+		error("Unable to get list of pixmap formats from display.\n");
+		XCloseDisplay(g_display);
+		return False;
+	}
+
+	/* Search for best TrueColor visual */
+	template.class = TrueColor;
+	template.screen = screen_num;
+	vmatches =
+		XGetVisualInfo(g_display, VisualClassMask | VisualScreenMask, &template,
+			       &visuals_count);
+	g_visual = NULL;
+	g_no_translate_image = False;
+	g_compatible_arch = False;
+	if (vmatches != NULL)
+	{
+		for (i = 0; i < visuals_count; ++i)
+		{
+			XVisualInfo *visual_info = &vmatches[i];
+			RD_BOOL can_translate_to_bpp = False;
+			int j;
+
+			/* Try to find a no-translation visual that'll
+			   allow us to use RDP bitmaps directly as ZPixmaps. */
+			if (!g_xserver_be && (((visual_info->depth == 15) &&
+					       /* R5G5B5 */
+					       (visual_info->red_mask == 0x7c00) &&
+					       (visual_info->green_mask == 0x3e0) &&
+					       (visual_info->blue_mask == 0x1f)) ||
+					      ((visual_info->depth == 16) &&
+					       /* R5G6B5 */
+					       (visual_info->red_mask == 0xf800) &&
+					       (visual_info->green_mask == 0x7e0) &&
+					       (visual_info->blue_mask == 0x1f)) ||
+					      ((visual_info->depth == 24) &&
+					       /* R8G8B8 */
+					       (visual_info->red_mask == 0xff0000) &&
+					       (visual_info->green_mask == 0xff00) &&
+					       (visual_info->blue_mask == 0xff))))
+			{
+				g_visual = visual_info->visual;
+				g_depth = visual_info->depth;
+				g_compatible_arch = !g_host_be;
+				g_no_translate_image = (visual_info->depth == g_server_depth);
+				if (g_no_translate_image)
+					/* We found the best visual */
+					break;
+			}
+			else
+			{
+				g_compatible_arch = False;
+			}
+
+			if (visual_info->depth > 24)
+			{
+				/* Avoid 32-bit visuals and likes like the plague.
+				   They're either untested or proven to work bad
+				   (e.g. nvidia's Composite 32-bit visual).
+				   Most implementation offer a 24-bit visual anyway. */
+				continue;
+			}
+
+			/* Only care for visuals, for whose BPPs (not depths!)
+			   we have a translateXtoY function. */
+			for (j = 0; j < pixmap_formats_count; ++j)
+			{
+				if (pfm[j].depth == visual_info->depth)
+				{
+					if ((pfm[j].bits_per_pixel == 16) ||
+					    (pfm[j].bits_per_pixel == 24) ||
+					    (pfm[j].bits_per_pixel == 32))
+					{
+						can_translate_to_bpp = True;
+					}
+					break;
+				}
+			}
+
+			/* Prefer formats which have the most colour depth.
+			   We're being truly aristocratic here, minding each
+			   weight on its own. */
+			if (can_translate_to_bpp)
+			{
+				unsigned vis_red_weight =
+					calculate_mask_weight(visual_info->red_mask);
+				unsigned vis_green_weight =
+					calculate_mask_weight(visual_info->green_mask);
+				unsigned vis_blue_weight =
+					calculate_mask_weight(visual_info->blue_mask);
+				if ((vis_red_weight >= red_weight)
+				    && (vis_green_weight >= green_weight)
+				    && (vis_blue_weight >= blue_weight))
+				{
+					red_weight = vis_red_weight;
+					green_weight = vis_green_weight;
+					blue_weight = vis_blue_weight;
+					g_visual = visual_info->visual;
+					g_depth = visual_info->depth;
+				}
+			}
+		}
+		XFree(vmatches);
+	}
+
+	if (g_visual != NULL)
+	{
+		g_owncolmap = False;
+		calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
+		calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
+		calculate_shifts(g_visual->blue_mask, &g_blue_shift_r, &g_blue_shift_l);
+	}
+	else
+	{
+		template.class = PseudoColor;
+		template.depth = 8;
+		template.colormap_size = 256;
+		vmatches =
+			XGetVisualInfo(g_display,
+				       VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
+				       &template, &visuals_count);
+		if (vmatches == NULL)
+		{
+			error("No usable TrueColor or PseudoColor visuals on this display.\n");
+			XCloseDisplay(g_display);
+			XFree(pfm);
+			return False;
+		}
+
+		/* we use a colourmap, so the default visual should do */
+		g_owncolmap = True;
+		g_visual = vmatches[0].visual;
+		g_depth = vmatches[0].depth;
+	}
+
+	g_bpp = 0;
+	for (i = 0; i < pixmap_formats_count; ++i)
+	{
+		XPixmapFormatValues *pf = &pfm[i];
+		if (pf->depth == g_depth)
+		{
+			g_bpp = pf->bits_per_pixel;
+
+			if (g_no_translate_image)
+			{
+				switch (g_server_depth)
+				{
+					case 15:
+					case 16:
+						if (g_bpp != 16)
+							g_no_translate_image = False;
+						break;
+					case 24:
+						/* Yes, this will force image translation
+						   on most modern servers which use 32 bits
+						   for R8G8B8. */
+						if (g_bpp != 24)
+							g_no_translate_image = False;
+						break;
+					default:
+						g_no_translate_image = False;
+						break;
+				}
+			}
+
+			/* Pixmap formats list is a depth-to-bpp mapping --
+			   there's just a single entry for every depth,
+			   so we can safely break here */
+			break;
+		}
+	}
+	XFree(pfm);
+	pfm = NULL;
+	return True;
+}
+
+static XErrorHandler g_old_error_handler;
+static RD_BOOL g_error_expected = False;
+
+/* Check if the X11 window corresponding to a seamless window with
+   specified id exists. */
+RD_BOOL
+sw_window_exists(unsigned long id)
+{
+	seamless_window *sw;
+	char *name;
+	Status sts = 0;
+
+	sw = sw_get_window_by_id(id);
+	if (!sw)
+		return False;
+
+	g_error_expected = True;
+	sts = XFetchName(g_display, sw->wnd, &name);
+	g_error_expected = False;
+	if (sts)
+	{
+		XFree(name);
+	}
+
+	return sts;
+}
+
+static int
+error_handler(Display * dpy, XErrorEvent * eev)
+{
+	if (g_error_expected)
+		return 0;
+
+	return g_old_error_handler(dpy, eev);
+}
+
+/* Initialize the UI. This is done once per process. */
+RD_BOOL
+ui_init(void)
+{
+	int screen_num;
+
+	g_display = XOpenDisplay(NULL);
+	if (g_display == NULL)
+	{
+		error("Failed to open display: %s\n", XDisplayName(NULL));
+		return False;
+	}
+
+	{
+		uint16 endianess_test = 1;
+		g_host_be = !(RD_BOOL) (*(uint8 *) (&endianess_test));
+	}
+
+	g_old_error_handler = XSetErrorHandler(error_handler);
+	g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
+	screen_num = DefaultScreen(g_display);
+	g_x_socket = ConnectionNumber(g_display);
+	g_screen = ScreenOfDisplay(g_display, screen_num);
+	g_depth = DefaultDepthOfScreen(g_screen);
+
+	if (!select_visual(screen_num))
+		return False;
+
+	if (g_no_translate_image)
+	{
+		DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
+	}
+
+	if (g_server_depth > g_bpp)
+	{
+		warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
+			g_server_depth, g_bpp);
+	}
+
+	DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
+	       g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
+
+	if (!g_owncolmap)
+	{
+		g_xcolmap =
+			XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
+					AllocNone);
+		if (g_depth <= 8)
+			warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", g_depth);
+	}
+
+	if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
+	{
+		warning("External BackingStore not available. Using internal.\n");
+		g_ownbackstore = True;
+	}
+
+	g_mod_map = XGetModifierMapping(g_display);
+	xwin_refresh_pointer_map();
+
+	xkeymap_init();
+
+	if (g_enable_compose)
+		g_IM = XOpenIM(g_display, NULL, NULL, NULL);
+
+	xclip_init();
+	ewmh_init();
+	if (g_seamless_rdp)
+	{
+		seamless_init();
+	}
+
+	DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
+
+	return True;
+}
+
+
+/* 
+   Initialize connection specific data, such as session size. 
+ */
+void
+ui_init_connection(void)
+{
+	/*
+	 * Determine desktop size
+	 */
+	if (g_fullscreen)
+	{
+		g_width = WidthOfScreen(g_screen);
+		g_height = HeightOfScreen(g_screen);
+		g_using_full_workarea = True;
+	}
+	else if (g_sizeopt < 0)
+	{
+		/* Percent of screen */
+		if (-g_sizeopt >= 100)
+			g_using_full_workarea = True;
+		g_height = HeightOfScreen(g_screen) * (-g_sizeopt) / 100;
+		g_width = WidthOfScreen(g_screen) * (-g_sizeopt) / 100;
+	}
+	else if (g_sizeopt == 1)
+	{
+		/* Fetch geometry from _NET_WORKAREA */
+		uint32 x, y, cx, cy;
+		if (get_current_workarea(&x, &y, &cx, &cy) == 0)
+		{
+			g_width = cx;
+			g_height = cy;
+			g_using_full_workarea = True;
+		}
+		else
+		{
+			warning("Failed to get workarea: probably your window manager does not support extended hints\n");
+			g_width = WidthOfScreen(g_screen);
+			g_height = HeightOfScreen(g_screen);
+		}
+	}
+
+	/* make sure width is a multiple of 4 */
+	g_width = (g_width + 3) & ~3;
+}
+
+
+void
+ui_deinit(void)
+{
+	xclip_deinit();
+
+	if (g_IM != NULL)
+		XCloseIM(g_IM);
+
+	if (g_null_cursor != NULL)
+		ui_destroy_cursor(g_null_cursor);
+
+	XFreeModifiermap(g_mod_map);
+
+	XFreeGC(g_display, g_gc);
+	XCloseDisplay(g_display);
+	g_display = NULL;
+}
+
+
+static void
+get_window_attribs(XSetWindowAttributes * attribs)
+{
+	attribs->background_pixel = BlackPixelOfScreen(g_screen);
+	attribs->border_pixel = WhitePixelOfScreen(g_screen);
+	attribs->backing_store = g_ownbackstore ? NotUseful : Always;
+	attribs->override_redirect = g_fullscreen;
+	attribs->colormap = g_xcolmap;
+}
+
+static void
+get_input_mask(long *input_mask)
+{
+	*input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
+		VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
+
+	if (g_sendmotion)
+		*input_mask |= PointerMotionMask;
+	if (g_ownbackstore)
+		*input_mask |= ExposureMask;
+	if (g_fullscreen || g_grab_keyboard)
+		*input_mask |= EnterWindowMask;
+	if (g_grab_keyboard)
+		*input_mask |= LeaveWindowMask;
+}
+
+RD_BOOL
+ui_create_window(void)
+{
+	uint8 null_pointer_mask[1] = { 0x80 };
+	uint8 null_pointer_data[24] = { 0x00 };
+
+	XSetWindowAttributes attribs;
+	XClassHint *classhints;
+	XSizeHints *sizehints;
+	int wndwidth, wndheight;
+	long input_mask, ic_input_mask;
+	XEvent xevent;
+
+	wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
+	wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
+
+	/* Handle -x-y portion of geometry string */
+	if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
+		g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
+	if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
+		g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
+
+	get_window_attribs(&attribs);
+
+	g_wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), g_xpos, g_ypos, wndwidth,
+			      wndheight, 0, g_depth, InputOutput, g_visual,
+			      CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
+			      CWBorderPixel, &attribs);
+
+	if (g_gc == NULL)
+	{
+		g_gc = XCreateGC(g_display, g_wnd, 0, NULL);
+		ui_reset_clip();
+	}
+
+	if (g_create_bitmap_gc == NULL)
+		g_create_bitmap_gc = XCreateGC(g_display, g_wnd, 0, NULL);
+
+	if ((g_ownbackstore) && (g_backstore == 0))
+	{
+		g_backstore = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
+
+		/* clear to prevent rubbish being exposed at startup */
+		XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
+		XFillRectangle(g_display, g_backstore, g_gc, 0, 0, g_width, g_height);
+	}
+
+	XStoreName(g_display, g_wnd, g_title);
+	ewmh_set_wm_name(g_wnd, g_title);
+
+	if (g_hide_decorations)
+		mwm_hide_decorations(g_wnd);
+
+	classhints = XAllocClassHint();
+	if (classhints != NULL)
+	{
+		classhints->res_name = classhints->res_class = "rdesktop";
+		XSetClassHint(g_display, g_wnd, classhints);
+		XFree(classhints);
+	}
+
+	sizehints = XAllocSizeHints();
+	if (sizehints)
+	{
+		sizehints->flags = PMinSize | PMaxSize;
+		if (g_pos)
+			sizehints->flags |= PPosition;
+		sizehints->min_width = sizehints->max_width = g_width;
+		sizehints->min_height = sizehints->max_height = g_height;
+		XSetWMNormalHints(g_display, g_wnd, sizehints);
+		XFree(sizehints);
+	}
+
+	if (g_embed_wnd)
+	{
+		XReparentWindow(g_display, g_wnd, (Window) g_embed_wnd, 0, 0);
+	}
+
+	get_input_mask(&input_mask);
+
+	if (g_IM != NULL)
+	{
+		g_IC = XCreateIC(g_IM, XNInputStyle, (XIMPreeditNothing | XIMStatusNothing),
+				 XNClientWindow, g_wnd, XNFocusWindow, g_wnd, NULL);
+
+		if ((g_IC != NULL)
+		    && (XGetICValues(g_IC, XNFilterEvents, &ic_input_mask, NULL) == NULL))
+			input_mask |= ic_input_mask;
+	}
+
+	XSelectInput(g_display, g_wnd, input_mask);
+#ifdef HAVE_XRANDR
+	XSelectInput(g_display, RootWindowOfScreen(g_screen), StructureNotifyMask);
+#endif
+	XMapWindow(g_display, g_wnd);
+
+	/* wait for VisibilityNotify */
+	do
+	{
+		XMaskEvent(g_display, VisibilityChangeMask, &xevent);
+	}
+	while (xevent.type != VisibilityNotify);
+	g_Unobscured = xevent.xvisibility.state == VisibilityUnobscured;
+
+	g_focused = False;
+	g_mouse_in_wnd = False;
+
+	/* handle the WM_DELETE_WINDOW protocol */
+	g_protocol_atom = XInternAtom(g_display, "WM_PROTOCOLS", True);
+	g_kill_atom = XInternAtom(g_display, "WM_DELETE_WINDOW", True);
+	XSetWMProtocols(g_display, g_wnd, &g_kill_atom, 1);
+
+	/* create invisible 1x1 cursor to be used as null cursor */
+	if (g_null_cursor == NULL)
+		g_null_cursor =
+			ui_create_cursor(0, 0, 1, 1, null_pointer_mask, null_pointer_data, 24);
+
+	if (g_seamless_rdp)
+	{
+		seamless_reset_state();
+		seamless_restack_test();
+	}
+
+	return True;
+}
+
+void
+ui_resize_window()
+{
+	XSizeHints *sizehints;
+	Pixmap bs;
+
+	sizehints = XAllocSizeHints();
+	if (sizehints)
+	{
+		sizehints->flags = PMinSize | PMaxSize;
+		sizehints->min_width = sizehints->max_width = g_width;
+		sizehints->min_height = sizehints->max_height = g_height;
+		XSetWMNormalHints(g_display, g_wnd, sizehints);
+		XFree(sizehints);
+	}
+
+	if (!(g_fullscreen || g_embed_wnd))
+	{
+		XResizeWindow(g_display, g_wnd, g_width, g_height);
+	}
+
+	/* create new backstore pixmap */
+	if (g_backstore != 0)
+	{
+		bs = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
+		XSetForeground(g_display, g_gc, BlackPixelOfScreen(g_screen));
+		XFillRectangle(g_display, bs, g_gc, 0, 0, g_width, g_height);
+		XCopyArea(g_display, g_backstore, bs, g_gc, 0, 0, g_width, g_height, 0, 0);
+		XFreePixmap(g_display, g_backstore);
+		g_backstore = bs;
+	}
+}
+
+RD_BOOL
+ui_have_window()
+{
+	return g_wnd ? True : False;
+}
+
+void
+ui_destroy_window(void)
+{
+	if (g_IC != NULL)
+		XDestroyIC(g_IC);
+
+	XDestroyWindow(g_display, g_wnd);
+	g_wnd = 0;
+
+	if (g_backstore)
+	{
+		XFreePixmap(g_display, g_backstore);
+		g_backstore = 0;
+	}
+}
+
+void
+xwin_toggle_fullscreen(void)
+{
+	Pixmap contents = 0;
+
+	if (g_seamless_active)
+		/* Turn off SeamlessRDP mode */
+		ui_seamless_toggle();
+
+	if (!g_ownbackstore)
+	{
+		/* need to save contents of window */
+		contents = XCreatePixmap(g_display, g_wnd, g_width, g_height, g_depth);
+		XCopyArea(g_display, g_wnd, contents, g_gc, 0, 0, g_width, g_height, 0, 0);
+	}
+
+	ui_destroy_window();
+	g_fullscreen = !g_fullscreen;
+	ui_create_window();
+
+	XDefineCursor(g_display, g_wnd, g_current_cursor);
+
+	if (!g_ownbackstore)
+	{
+		XCopyArea(g_display, contents, g_wnd, g_gc, 0, 0, g_width, g_height, 0, 0);
+		XFreePixmap(g_display, contents);
+	}
+}
+
+static void
+handle_button_event(XEvent xevent, RD_BOOL down)
+{
+	uint16 button, flags = 0;
+	g_last_gesturetime = xevent.xbutton.time;
+	/* Reverse the pointer button mapping, e.g. in the case of
+	   "left-handed mouse mode"; the RDP session expects to
+	   receive physical buttons (true in mstsc as well) and
+	   logical button behavior depends on the remote desktop's own
+	   mouse settings */
+	xevent.xbutton.button = g_pointer_log_to_phys_map[xevent.xbutton.button - 1];
+	button = xkeymap_translate_button(xevent.xbutton.button);
+	if (button == 0)
+		return;
+
+	if (down)
+		flags = MOUSE_FLAG_DOWN;
+
+	/* Stop moving window when button is released, regardless of cursor position */
+	if (g_moving_wnd && (xevent.type == ButtonRelease))
+		g_moving_wnd = False;
+
+	/* If win_button_size is nonzero, enable single app mode */
+	if (xevent.xbutton.y < g_win_button_size)
+	{
+		/*  Check from right to left: */
+		if (xevent.xbutton.x >= g_width - g_win_button_size)
+		{
+			/* The close button, continue */
+			;
+		}
+		else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
+		{
+			/* The maximize/restore button. Do not send to
+			   server.  It might be a good idea to change the
+			   cursor or give some other visible indication
+			   that rdesktop inhibited this click */
+			if (xevent.type == ButtonPress)
+				return;
+		}
+		else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
+		{
+			/* The minimize button. Iconify window. */
+			if (xevent.type == ButtonRelease)
+			{
+				/* Release the mouse button outside the minimize button, to prevent the
+				   actual minimazation to happen */
+				rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
+				XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
+				return;
+			}
+		}
+		else if (xevent.xbutton.x <= g_win_button_size)
+		{
+			/* The system menu. Ignore. */
+			if (xevent.type == ButtonPress)
+				return;
+		}
+		else
+		{
+			/* The title bar. */
+			if (xevent.type == ButtonPress)
+			{
+				if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
+				{
+					g_moving_wnd = True;
+					g_move_x_offset = xevent.xbutton.x;
+					g_move_y_offset = xevent.xbutton.y;
+				}
+				return;
+			}
+		}
+	}
+
+	/* Ignore mouse scroll button release event which will be handled as an additional
+	 * scrolldown event on the Windows side.
+	 */
+	if (!down && (button == MOUSE_FLAG_BUTTON4 || button == MOUSE_FLAG_BUTTON5))
+	{
+		return;
+	}
+
+	if (xevent.xmotion.window == g_wnd)
+	{
+		rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
+			       flags | button, xevent.xbutton.x, xevent.xbutton.y);
+	}
+	else
+	{
+		/* SeamlessRDP */
+		rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
+			       flags | button, xevent.xbutton.x_root, xevent.xbutton.y_root);
+	}
+}
+
+
+/* Process events in Xlib queue
+   Returns 0 after user quit, 1 otherwise */
+static int
+xwin_process_events(void)
+{
+	XEvent xevent;
+	KeySym keysym;
+	uint32 ev_time;
+	char str[256];
+	Status status;
+	int events = 0;
+	seamless_window *sw;
+
+	while ((XPending(g_display) > 0) && events++ < 20)
+	{
+		XNextEvent(g_display, &xevent);
+
+		if (!g_wnd)
+			/* Ignore events between ui_destroy_window and ui_create_window */
+			continue;
+
+		/* Also ignore root window events except ConfigureNotify */
+		if (xevent.type != ConfigureNotify
+		    && xevent.xany.window == DefaultRootWindow(g_display))
+			continue;
+
+		if ((g_IC != NULL) && (XFilterEvent(&xevent, None) == True))
+		{
+			DEBUG_KBD(("Filtering event\n"));
+			continue;
+		}
+
+		switch (xevent.type)
+		{
+			case VisibilityNotify:
+				if (xevent.xvisibility.window == g_wnd)
+					g_Unobscured =
+						xevent.xvisibility.state == VisibilityUnobscured;
+
+				break;
+			case ClientMessage:
+				/* the window manager told us to quit */
+				if ((xevent.xclient.message_type == g_protocol_atom)
+				    && ((Atom) xevent.xclient.data.l[0] == g_kill_atom))
+				{
+					/* When killing a seamless window, close the window on the
+					   serverside instead of terminating rdesktop */
+					sw = sw_get_window_by_wnd(xevent.xclient.window);
+					if (!sw)
+						/* Otherwise, quit */
+						return 0;
+					/* send seamless destroy process message */
+					seamless_send_destroy(sw->id);
+				}
+				break;
+
+			case KeyPress:
+				g_last_gesturetime = xevent.xkey.time;
+				if (g_IC != NULL)
+					/* Multi_key compatible version */
+				{
+					XmbLookupString(g_IC,
+							&xevent.xkey, str, sizeof(str), &keysym,
+							&status);
+					if (!((status == XLookupKeySym) || (status == XLookupBoth)))
+					{
+						error("XmbLookupString failed with status 0x%x\n",
+						      status);
+						break;
+					}
+				}
+				else
+				{
+					/* Plain old XLookupString */
+					DEBUG_KBD(("\nNo input context, using XLookupString\n"));
+					XLookupString((XKeyEvent *) & xevent,
+						      str, sizeof(str), &keysym, NULL);
+				}
+
+				DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
+					   get_ksname(keysym)));
+
+				set_keypress_keysym(xevent.xkey.keycode, keysym);
+				ev_time = time(NULL);
+				if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
+					break;
+
+				xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
+						  ev_time, True, 0);
+				break;
+
+			case KeyRelease:
+				g_last_gesturetime = xevent.xkey.time;
+				XLookupString((XKeyEvent *) & xevent, str,
+					      sizeof(str), &keysym, NULL);
+
+				DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
+					   get_ksname(keysym)));
+
+				keysym = reset_keypress_keysym(xevent.xkey.keycode, keysym);
+				ev_time = time(NULL);
+				if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
+					break;
+
+				xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
+						  ev_time, False, 0);
+				break;
+
+			case ButtonPress:
+				handle_button_event(xevent, True);
+				break;
+
+			case ButtonRelease:
+				handle_button_event(xevent, False);
+				break;
+
+			case MotionNotify:
+				if (g_moving_wnd)
+				{
+					XMoveWindow(g_display, g_wnd,
+						    xevent.xmotion.x_root - g_move_x_offset,
+						    xevent.xmotion.y_root - g_move_y_offset);
+					break;
+				}
+
+				if (g_fullscreen && !g_focused)
+					XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
+						       CurrentTime);
+
+				if (xevent.xmotion.window == g_wnd)
+				{
+					rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
+						       xevent.xmotion.x, xevent.xmotion.y);
+				}
+				else
+				{
+					/* SeamlessRDP */
+					rdp_send_input(time(NULL), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE,
+						       xevent.xmotion.x_root,
+						       xevent.xmotion.y_root);
+				}
+				break;
+
+			case FocusIn:
+				if (xevent.xfocus.mode == NotifyGrab)
+					break;
+				g_focused = True;
+				reset_modifier_keys();
+				if (g_grab_keyboard && g_mouse_in_wnd)
+					XGrabKeyboard(g_display, g_wnd, True,
+						      GrabModeAsync, GrabModeAsync, CurrentTime);
+
+				sw = sw_get_window_by_wnd(xevent.xfocus.window);
+				if (!sw)
+					break;
+
+				/* Menu windows are real X11 windows,
+				   with focus. When such a window is
+				   destroyed, focus is reverted to the
+				   main application window, which
+				   would cause us to send FOCUS. This
+				   breaks window switching in, say,
+				   Seamonkey. We shouldn't need to
+				   send FOCUS: Windows should also
+				   revert focus to some other window
+				   when the menu window is
+				   destroyed. So, we only send FOCUS
+				   if the previous focus window still
+				   exists. */
+				if (sw->id != g_seamless_focused)
+				{
+
+					if (sw_window_exists(g_seamless_focused))
+						seamless_send_focus(sw->id, 0);
+					g_seamless_focused = sw->id;
+				}
+				break;
+
+			case FocusOut:
+				if (xevent.xfocus.mode == NotifyUngrab)
+					break;
+				g_focused = False;
+				if (xevent.xfocus.mode == NotifyWhileGrabbed)
+					XUngrabKeyboard(g_display, CurrentTime);
+				break;
+
+			case EnterNotify:
+				/* we only register for this event when in fullscreen mode */
+				/* or grab_keyboard */
+				g_mouse_in_wnd = True;
+				if (g_fullscreen)
+				{
+					XSetInputFocus(g_display, g_wnd, RevertToPointerRoot,
+						       CurrentTime);
+					break;
+				}
+				if (g_focused)
+					XGrabKeyboard(g_display, g_wnd, True,
+						      GrabModeAsync, GrabModeAsync, CurrentTime);
+				break;
+
+			case LeaveNotify:
+				/* we only register for this event when grab_keyboard */
+				g_mouse_in_wnd = False;
+				XUngrabKeyboard(g_display, CurrentTime);
+				break;
+
+			case Expose:
+				if (xevent.xexpose.window == g_wnd)
+				{
+					XCopyArea(g_display, g_backstore, xevent.xexpose.window,
+						  g_gc,
+						  xevent.xexpose.x, xevent.xexpose.y,
+						  xevent.xexpose.width, xevent.xexpose.height,
+						  xevent.xexpose.x, xevent.xexpose.y);
+				}
+				else
+				{
+					sw = sw_get_window_by_wnd(xevent.xexpose.window);
+					if (!sw)
+						break;
+					XCopyArea(g_display, g_backstore,
+						  xevent.xexpose.window, g_gc,
+						  xevent.xexpose.x + sw->xoffset,
+						  xevent.xexpose.y + sw->yoffset,
+						  xevent.xexpose.width,
+						  xevent.xexpose.height, xevent.xexpose.x,
+						  xevent.xexpose.y);
+				}
+
+				break;
+
+			case MappingNotify:
+				/* Refresh keyboard mapping if it has changed. This is important for
+				   Xvnc, since it allocates keycodes dynamically */
+				if (xevent.xmapping.request == MappingKeyboard
+				    || xevent.xmapping.request == MappingModifier)
+					XRefreshKeyboardMapping(&xevent.xmapping);
+
+				if (xevent.xmapping.request == MappingModifier)
+				{
+					XFreeModifiermap(g_mod_map);
+					g_mod_map = XGetModifierMapping(g_display);
+				}
+
+				if (xevent.xmapping.request == MappingPointer)
+				{
+					xwin_refresh_pointer_map();
+				}
+
+				break;
+
+				/* clipboard stuff */
+			case SelectionNotify:
+				xclip_handle_SelectionNotify(&xevent.xselection);
+				break;
+			case SelectionRequest:
+				xclip_handle_SelectionRequest(&xevent.xselectionrequest);
+				break;
+			case SelectionClear:
+				xclip_handle_SelectionClear();
+				break;
+			case PropertyNotify:
+				xclip_handle_PropertyNotify(&xevent.xproperty);
+				if (xevent.xproperty.window == g_wnd)
+					break;
+				if (xevent.xproperty.window == DefaultRootWindow(g_display))
+					break;
+
+				/* seamless */
+				sw = sw_get_window_by_wnd(xevent.xproperty.window);
+				if (!sw)
+					break;
+
+				if ((xevent.xproperty.atom == g_net_wm_state_atom)
+				    && (xevent.xproperty.state == PropertyNewValue))
+				{
+					sw->state = ewmh_get_window_state(sw->wnd);
+					seamless_send_state(sw->id, sw->state, 0);
+				}
+
+				if ((xevent.xproperty.atom == g_net_wm_desktop_atom)
+				    && (xevent.xproperty.state == PropertyNewValue))
+				{
+					sw->desktop = ewmh_get_window_desktop(sw->wnd);
+					sw_all_to_desktop(sw->wnd, sw->desktop);
+				}
+
+				break;
+			case MapNotify:
+				if (!g_seamless_active)
+					rdp_send_client_window_status(1);
+				break;
+			case UnmapNotify:
+				if (!g_seamless_active)
+					rdp_send_client_window_status(0);
+				break;
+			case ConfigureNotify:
+#ifdef HAVE_XRANDR
+				if ((g_sizeopt || g_fullscreen)
+				    && xevent.xconfigure.window == DefaultRootWindow(g_display))
+				{
+					if (xevent.xconfigure.width != WidthOfScreen(g_screen)
+					    || xevent.xconfigure.height != HeightOfScreen(g_screen))
+					{
+						XRRUpdateConfiguration(&xevent);
+						XSync(g_display, False);
+						g_pending_resize = True;
+					}
+
+				}
+#endif
+				if (!g_seamless_active)
+					break;
+
+				sw = sw_get_window_by_wnd(xevent.xconfigure.window);
+				if (!sw)
+					break;
+
+				gettimeofday(sw->position_timer, NULL);
+				if (sw->position_timer->tv_usec + SEAMLESSRDP_POSITION_TIMER >=
+				    1000000)
+				{
+					sw->position_timer->tv_usec +=
+						SEAMLESSRDP_POSITION_TIMER - 1000000;
+					sw->position_timer->tv_sec += 1;
+				}
+				else
+				{
+					sw->position_timer->tv_usec += SEAMLESSRDP_POSITION_TIMER;
+				}
+
+				sw_handle_restack(sw);
+				break;
+		}
+	}
+	/* Keep going */
+	return 1;
+}
+
+/* Returns 0 after user quit, 1 otherwise */
+int
+ui_select(int rdp_socket)
+{
+	int n;
+	fd_set rfds, wfds;
+	struct timeval tv;
+	RD_BOOL s_timeout = False;
+
+	while (True)
+	{
+		n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
+		/* Process any events already waiting */
+		if (!xwin_process_events())
+			/* User quit */
+			return 0;
+
+		if (g_seamless_active)
+			sw_check_timers();
+
+		FD_ZERO(&rfds);
+		FD_ZERO(&wfds);
+		FD_SET(rdp_socket, &rfds);
+		FD_SET(g_x_socket, &rfds);
+
+		/* default timeout */
+		tv.tv_sec = 60;
+		tv.tv_usec = 0;
+
+#ifdef WITH_RDPSND
+		rdpsnd_add_fds(&n, &rfds, &wfds, &tv);
+#endif
+
+		/* add redirection handles */
+		rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
+		seamless_select_timeout(&tv);
+
+		/* add ctrl slaves handles */
+		ctrl_add_fds(&n, &rfds);
+
+		n++;
+
+		switch (select(n, &rfds, &wfds, NULL, &tv))
+		{
+			case -1:
+				error("select: %s\n", strerror(errno));
+
+			case 0:
+#ifdef WITH_RDPSND
+				rdpsnd_check_fds(&rfds, &wfds);
+#endif
+
+				/* Abort serial read calls */
+				if (s_timeout)
+					rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) True);
+				continue;
+		}
+
+#ifdef WITH_RDPSND
+		rdpsnd_check_fds(&rfds, &wfds);
+#endif
+
+		rdpdr_check_fds(&rfds, &wfds, (RD_BOOL) False);
+
+		ctrl_check_fds(&rfds, &wfds);
+
+		if (FD_ISSET(rdp_socket, &rfds))
+			return 1;
+
+	}
+}
+
+void
+ui_move_pointer(int x, int y)
+{
+	XWarpPointer(g_display, g_wnd, g_wnd, 0, 0, 0, 0, x, y);
+}
+
+RD_HBITMAP
+ui_create_bitmap(int width, int height, uint8 * data)
+{
+	XImage *image;
+	Pixmap bitmap;
+	uint8 *tdata;
+	int bitmap_pad;
+
+	if (g_server_depth == 8)
+	{
+		bitmap_pad = 8;
+	}
+	else
+	{
+		bitmap_pad = g_bpp;
+
+		if (g_bpp == 24)
+			bitmap_pad = 32;
+	}
+
+	tdata = (g_owncolmap ? data : translate_image(width, height, data));
+	bitmap = XCreatePixmap(g_display, g_wnd, width, height, g_depth);
+	image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
+			     (char *) tdata, width, height, bitmap_pad, 0);
+
+	XPutImage(g_display, bitmap, g_create_bitmap_gc, image, 0, 0, 0, 0, width, height);
+
+	XFree(image);
+	if (tdata != data)
+		xfree(tdata);
+	return (RD_HBITMAP) bitmap;
+}
+
+void
+ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data)
+{
+	XImage *image;
+	uint8 *tdata;
+	int bitmap_pad;
+
+	if (g_server_depth == 8)
+	{
+		bitmap_pad = 8;
+	}
+	else
+	{
+		bitmap_pad = g_bpp;
+
+		if (g_bpp == 24)
+			bitmap_pad = 32;
+	}
+
+	tdata = (g_owncolmap ? data : translate_image(width, height, data));
+	image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
+			     (char *) tdata, width, height, bitmap_pad, 0);
+
+	if (g_ownbackstore)
+	{
+		XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
+		XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
+		ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+					(g_display, g_backstore, sw->wnd, g_gc, x, y, cx, cy,
+					 x - sw->xoffset, y - sw->yoffset));
+	}
+	else
+	{
+		XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
+		ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+					(g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
+					 x - sw->xoffset, y - sw->yoffset));
+	}
+
+	XFree(image);
+	if (tdata != data)
+		xfree(tdata);
+}
+
+void
+ui_destroy_bitmap(RD_HBITMAP bmp)
+{
+	XFreePixmap(g_display, (Pixmap) bmp);
+}
+
+RD_HGLYPH
+ui_create_glyph(int width, int height, uint8 * data)
+{
+	XImage *image;
+	Pixmap bitmap;
+	int scanline;
+
+	scanline = (width + 7) / 8;
+
+	bitmap = XCreatePixmap(g_display, g_wnd, width, height, 1);
+	if (g_create_glyph_gc == 0)
+		g_create_glyph_gc = XCreateGC(g_display, bitmap, 0, NULL);
+
+	image = XCreateImage(g_display, g_visual, 1, ZPixmap, 0, (char *) data,
+			     width, height, 8, scanline);
+	image->byte_order = MSBFirst;
+	image->bitmap_bit_order = MSBFirst;
+	XInitImage(image);
+
+	XPutImage(g_display, bitmap, g_create_glyph_gc, image, 0, 0, 0, 0, width, height);
+
+	XFree(image);
+	return (RD_HGLYPH) bitmap;
+}
+
+void
+ui_destroy_glyph(RD_HGLYPH glyph)
+{
+	XFreePixmap(g_display, (Pixmap) glyph);
+}
+
+/* convert next pixel to 32 bpp */
+static int
+get_next_xor_pixel(uint8 * xormask, int bpp, int *k)
+{
+	int rv = 0;
+	PixelColour pc;
+	uint8 *s8;
+	uint16 *s16;
+
+	switch (bpp)
+	{
+		case 1:
+			s8 = xormask + (*k) / 8;
+			rv = (*s8) & (0x80 >> ((*k) % 8));
+			rv = rv ? 0xffffff : 0;
+			(*k) += 1;
+			break;
+		case 8:
+			s8 = xormask + *k;
+			/* should use colour map */
+			rv = s8[0];
+			rv = rv ? 0xffffff : 0;
+			(*k) += 1;
+			break;
+		case 15:
+			s16 = (uint16 *) xormask;
+			SPLITCOLOUR15(s16[*k], pc);
+			rv = (pc.red << 16) | (pc.green << 8) | pc.blue;
+			(*k) += 1;
+			break;
+		case 16:
+			s16 = (uint16 *) xormask;
+			SPLITCOLOUR16(s16[*k], pc);
+			rv = (pc.red << 16) | (pc.green << 8) | pc.blue;
+			(*k) += 1;
+			break;
+		case 24:
+			s8 = xormask + *k;
+			rv = (s8[0] << 16) | (s8[1] << 8) | s8[2];
+			(*k) += 3;
+			break;
+		case 32:
+			s8 = xormask + *k;
+			rv = (s8[1] << 16) | (s8[2] << 8) | s8[3];
+			(*k) += 4;
+			break;
+		default:
+			error("unknown bpp in get_next_xor_pixel %d\n", bpp);
+			break;
+	}
+	return rv;
+}
+
+RD_HCURSOR
+ui_create_cursor(unsigned int x, unsigned int y, int width, int height,
+		 uint8 * andmask, uint8 * xormask, int bpp)
+{
+	RD_HGLYPH maskglyph, cursorglyph;
+	XColor bg, fg;
+	Cursor xcursor;
+	uint8 *cursor, *pcursor;
+	uint8 *mask, *pmask;
+	uint8 nextbit;
+	int scanline, offset, delta;
+	int i, j, k;
+
+	k = 0;
+	scanline = (width + 7) / 8;
+	offset = scanline * height;
+
+	cursor = (uint8 *) xmalloc(offset);
+	memset(cursor, 0, offset);
+
+	mask = (uint8 *) xmalloc(offset);
+	memset(mask, 0, offset);
+	if (bpp == 1)
+	{
+		offset = 0;
+		delta = scanline;
+	}
+	else
+	{
+		offset = scanline * height - scanline;
+		delta = -scanline;
+	}
+	/* approximate AND and XOR masks with a monochrome X pointer */
+	for (i = 0; i < height; i++)
+	{
+		pcursor = &cursor[offset];
+		pmask = &mask[offset];
+
+		for (j = 0; j < scanline; j++)
+		{
+			for (nextbit = 0x80; nextbit != 0; nextbit >>= 1)
+			{
+				if (get_next_xor_pixel(xormask, bpp, &k))
+				{
+					*pcursor |= (~(*andmask) & nextbit);
+					*pmask |= nextbit;
+				}
+				else
+				{
+					*pcursor |= ((*andmask) & nextbit);
+					*pmask |= (~(*andmask) & nextbit);
+				}
+			}
+
+			andmask++;
+			pcursor++;
+			pmask++;
+		}
+		offset += delta;
+	}
+
+	fg.red = fg.blue = fg.green = 0xffff;
+	bg.red = bg.blue = bg.green = 0x0000;
+	fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
+
+	cursorglyph = ui_create_glyph(width, height, cursor);
+	maskglyph = ui_create_glyph(width, height, mask);
+
+	xcursor =
+		XCreatePixmapCursor(g_display, (Pixmap) cursorglyph,
+				    (Pixmap) maskglyph, &fg, &bg, x, y);
+
+	ui_destroy_glyph(maskglyph);
+	ui_destroy_glyph(cursorglyph);
+	xfree(mask);
+	xfree(cursor);
+	return (RD_HCURSOR) xcursor;
+}
+
+void
+ui_set_cursor(RD_HCURSOR cursor)
+{
+	g_current_cursor = (Cursor) cursor;
+	XDefineCursor(g_display, g_wnd, g_current_cursor);
+	ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
+}
+
+void
+ui_destroy_cursor(RD_HCURSOR cursor)
+{
+	XFreeCursor(g_display, (Cursor) cursor);
+}
+
+void
+ui_set_null_cursor(void)
+{
+	ui_set_cursor(g_null_cursor);
+}
+
+#define MAKE_XCOLOR(xc,c) \
+		(xc)->red   = ((c)->red   << 8) | (c)->red; \
+		(xc)->green = ((c)->green << 8) | (c)->green; \
+		(xc)->blue  = ((c)->blue  << 8) | (c)->blue; \
+		(xc)->flags = DoRed | DoGreen | DoBlue;
+
+
+RD_HCOLOURMAP
+ui_create_colourmap(COLOURMAP * colours)
+{
+	COLOURENTRY *entry;
+	int i, ncolours = colours->ncolours;
+	if (!g_owncolmap)
+	{
+		uint32 *map = (uint32 *) xmalloc(sizeof(*g_colmap) * ncolours);
+		XColor xentry;
+		XColor xc_cache[256];
+		uint32 colour;
+		int colLookup = 256;
+		for (i = 0; i < ncolours; i++)
+		{
+			entry = &colours->colours[i];
+			MAKE_XCOLOR(&xentry, entry);
+
+			if (XAllocColor(g_display, g_xcolmap, &xentry) == 0)
+			{
+				/* Allocation failed, find closest match. */
+				int j = 256;
+				int nMinDist = 3 * 256 * 256;
+				long nDist = nMinDist;
+
+				/* only get the colors once */
+				while (colLookup--)
+				{
+					xc_cache[colLookup].pixel = colLookup;
+					xc_cache[colLookup].red = xc_cache[colLookup].green =
+						xc_cache[colLookup].blue = 0;
+					xc_cache[colLookup].flags = 0;
+					XQueryColor(g_display,
+						    DefaultColormap(g_display,
+								    DefaultScreen(g_display)),
+						    &xc_cache[colLookup]);
+				}
+				colLookup = 0;
+
+				/* approximate the pixel */
+				while (j--)
+				{
+					if (xc_cache[j].flags)
+					{
+						nDist = ((long) (xc_cache[j].red >> 8) -
+							 (long) (xentry.red >> 8)) *
+							((long) (xc_cache[j].red >> 8) -
+							 (long) (xentry.red >> 8)) +
+							((long) (xc_cache[j].green >> 8) -
+							 (long) (xentry.green >> 8)) *
+							((long) (xc_cache[j].green >> 8) -
+							 (long) (xentry.green >> 8)) +
+							((long) (xc_cache[j].blue >> 8) -
+							 (long) (xentry.blue >> 8)) *
+							((long) (xc_cache[j].blue >> 8) -
+							 (long) (xentry.blue >> 8));
+					}
+					if (nDist < nMinDist)
+					{
+						nMinDist = nDist;
+						xentry.pixel = j;
+					}
+				}
+			}
+			colour = xentry.pixel;
+
+			/* update our cache */
+			if (xentry.pixel < 256)
+			{
+				xc_cache[xentry.pixel].red = xentry.red;
+				xc_cache[xentry.pixel].green = xentry.green;
+				xc_cache[xentry.pixel].blue = xentry.blue;
+
+			}
+
+			map[i] = colour;
+		}
+		return map;
+	}
+	else
+	{
+		XColor *xcolours, *xentry;
+		Colormap map;
+
+		xcolours = (XColor *) xmalloc(sizeof(XColor) * ncolours);
+		for (i = 0; i < ncolours; i++)
+		{
+			entry = &colours->colours[i];
+			xentry = &xcolours[i];
+			xentry->pixel = i;
+			MAKE_XCOLOR(xentry, entry);
+		}
+
+		map = XCreateColormap(g_display, g_wnd, g_visual, AllocAll);
+		XStoreColors(g_display, map, xcolours, ncolours);
+
+		xfree(xcolours);
+		return (RD_HCOLOURMAP) map;
+	}
+}
+
+void
+ui_destroy_colourmap(RD_HCOLOURMAP map)
+{
+	if (!g_owncolmap)
+		xfree(map);
+	else
+		XFreeColormap(g_display, (Colormap) map);
+}
+
+void
+ui_set_colourmap(RD_HCOLOURMAP map)
+{
+	if (!g_owncolmap)
+	{
+		if (g_colmap)
+			xfree(g_colmap);
+
+		g_colmap = (uint32 *) map;
+	}
+	else
+	{
+		XSetWindowColormap(g_display, g_wnd, (Colormap) map);
+		ON_ALL_SEAMLESS_WINDOWS(XSetWindowColormap, (g_display, sw->wnd, (Colormap) map));
+	}
+}
+
+void
+ui_set_clip(int x, int y, int cx, int cy)
+{
+	g_clip_rectangle.x = x;
+	g_clip_rectangle.y = y;
+	g_clip_rectangle.width = cx;
+	g_clip_rectangle.height = cy;
+	XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
+}
+
+void
+ui_reset_clip(void)
+{
+	g_clip_rectangle.x = 0;
+	g_clip_rectangle.y = 0;
+	g_clip_rectangle.width = g_width;
+	g_clip_rectangle.height = g_height;
+	XSetClipRectangles(g_display, g_gc, 0, 0, &g_clip_rectangle, 1, YXBanded);
+}
+
+void
+ui_bell(void)
+{
+	XBell(g_display, 0);
+}
+
+void
+ui_destblt(uint8 opcode,
+	   /* dest */ int x, int y, int cx, int cy)
+{
+	SET_FUNCTION(opcode);
+	FILL_RECTANGLE(x, y, cx, cy);
+	RESET_FUNCTION(opcode);
+}
+
+static uint8 hatch_patterns[] = {
+	0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,	/* 0 - bsHorizontal */
+	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,	/* 1 - bsVertical */
+	0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,	/* 2 - bsFDiagonal */
+	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,	/* 3 - bsBDiagonal */
+	0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08,	/* 4 - bsCross */
+	0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81	/* 5 - bsDiagCross */
+};
+
+void
+ui_patblt(uint8 opcode,
+	  /* dest */ int x, int y, int cx, int cy,
+	  /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
+{
+	Pixmap fill;
+	uint8 i, ipattern[8];
+
+	SET_FUNCTION(opcode);
+
+	switch (brush->style)
+	{
+		case 0:	/* Solid */
+			SET_FOREGROUND(fgcolour);
+			FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
+			break;
+
+		case 2:	/* Hatch */
+			fill = (Pixmap) ui_create_glyph(8, 8,
+							hatch_patterns + brush->pattern[0] * 8);
+			SET_FOREGROUND(fgcolour);
+			SET_BACKGROUND(bgcolour);
+			XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
+			XSetStipple(g_display, g_gc, fill);
+			XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+			FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
+			XSetFillStyle(g_display, g_gc, FillSolid);
+			XSetTSOrigin(g_display, g_gc, 0, 0);
+			ui_destroy_glyph((RD_HGLYPH) fill);
+			break;
+
+		case 3:	/* Pattern */
+			if (brush->bd == 0)	/* rdp4 brush */
+			{
+				for (i = 0; i != 8; i++)
+					ipattern[7 - i] = brush->pattern[i];
+				fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
+				SET_FOREGROUND(bgcolour);
+				SET_BACKGROUND(fgcolour);
+				XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
+				XSetStipple(g_display, g_gc, fill);
+				XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+				FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
+				XSetFillStyle(g_display, g_gc, FillSolid);
+				XSetTSOrigin(g_display, g_gc, 0, 0);
+				ui_destroy_glyph((RD_HGLYPH) fill);
+			}
+			else if (brush->bd->colour_code > 1)	/* > 1 bpp */
+			{
+				fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
+				XSetFillStyle(g_display, g_gc, FillTiled);
+				XSetTile(g_display, g_gc, fill);
+				XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+				FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
+				XSetFillStyle(g_display, g_gc, FillSolid);
+				XSetTSOrigin(g_display, g_gc, 0, 0);
+				ui_destroy_bitmap((RD_HBITMAP) fill);
+			}
+			else
+			{
+				fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
+				SET_FOREGROUND(bgcolour);
+				SET_BACKGROUND(fgcolour);
+				XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
+				XSetStipple(g_display, g_gc, fill);
+				XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+				FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
+				XSetFillStyle(g_display, g_gc, FillSolid);
+				XSetTSOrigin(g_display, g_gc, 0, 0);
+				ui_destroy_glyph((RD_HGLYPH) fill);
+			}
+			break;
+
+		default:
+			unimpl("brush %d\n", brush->style);
+	}
+
+	RESET_FUNCTION(opcode);
+
+	if (g_ownbackstore)
+		XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
+	ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+				(g_display, g_ownbackstore ? g_backstore : g_wnd, sw->wnd, g_gc,
+				 x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
+}
+
+void
+ui_screenblt(uint8 opcode,
+	     /* dest */ int x, int y, int cx, int cy,
+	     /* src */ int srcx, int srcy)
+{
+	SET_FUNCTION(opcode);
+	if (g_ownbackstore)
+	{
+		XCopyArea(g_display, g_Unobscured ? g_wnd : g_backstore,
+			  g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
+		XCopyArea(g_display, g_backstore, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
+	}
+	else
+	{
+		XCopyArea(g_display, g_wnd, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
+	}
+
+	ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+				(g_display, g_ownbackstore ? g_backstore : g_wnd,
+				 sw->wnd, g_gc, x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
+
+	RESET_FUNCTION(opcode);
+}
+
+void
+ui_memblt(uint8 opcode,
+	  /* dest */ int x, int y, int cx, int cy,
+	  /* src */ RD_HBITMAP src, int srcx, int srcy)
+{
+	SET_FUNCTION(opcode);
+	XCopyArea(g_display, (Pixmap) src, g_wnd, g_gc, srcx, srcy, cx, cy, x, y);
+	ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+				(g_display, (Pixmap) src, sw->wnd, g_gc,
+				 srcx, srcy, cx, cy, x - sw->xoffset, y - sw->yoffset));
+	if (g_ownbackstore)
+		XCopyArea(g_display, (Pixmap) src, g_backstore, g_gc, srcx, srcy, cx, cy, x, y);
+	RESET_FUNCTION(opcode);
+}
+
+void
+ui_triblt(uint8 opcode,
+	  /* dest */ int x, int y, int cx, int cy,
+	  /* src */ RD_HBITMAP src, int srcx, int srcy,
+	  /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
+{
+	/* This is potentially difficult to do in general. Until someone
+	   comes up with a more efficient way of doing it I am using cases. */
+
+	switch (opcode)
+	{
+		case 0x69:	/* PDSxxn */
+			ui_memblt(ROP2_XOR, x, y, cx, cy, src, srcx, srcy);
+			ui_patblt(ROP2_NXOR, x, y, cx, cy, brush, bgcolour, fgcolour);
+			break;
+
+		case 0xb8:	/* PSDPxax */
+			ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
+			ui_memblt(ROP2_AND, x, y, cx, cy, src, srcx, srcy);
+			ui_patblt(ROP2_XOR, x, y, cx, cy, brush, bgcolour, fgcolour);
+			break;
+
+		case 0xc0:	/* PSa */
+			ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
+			ui_patblt(ROP2_AND, x, y, cx, cy, brush, bgcolour, fgcolour);
+			break;
+
+		default:
+			unimpl("triblt 0x%x\n", opcode);
+			ui_memblt(ROP2_COPY, x, y, cx, cy, src, srcx, srcy);
+	}
+}
+
+void
+ui_line(uint8 opcode,
+	/* dest */ int startx, int starty, int endx, int endy,
+	/* pen */ PEN * pen)
+{
+	SET_FUNCTION(opcode);
+	SET_FOREGROUND(pen->colour);
+	XDrawLine(g_display, g_wnd, g_gc, startx, starty, endx, endy);
+	ON_ALL_SEAMLESS_WINDOWS(XDrawLine, (g_display, sw->wnd, g_gc,
+					    startx - sw->xoffset, starty - sw->yoffset,
+					    endx - sw->xoffset, endy - sw->yoffset));
+	if (g_ownbackstore)
+		XDrawLine(g_display, g_backstore, g_gc, startx, starty, endx, endy);
+	RESET_FUNCTION(opcode);
+}
+
+void
+ui_rect(
+	       /* dest */ int x, int y, int cx, int cy,
+	       /* brush */ int colour)
+{
+	SET_FOREGROUND(colour);
+	FILL_RECTANGLE(x, y, cx, cy);
+}
+
+void
+ui_polygon(uint8 opcode,
+	   /* mode */ uint8 fillmode,
+	   /* dest */ RD_POINT * point, int npoints,
+	   /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
+{
+	uint8 style, i, ipattern[8];
+	Pixmap fill;
+
+	SET_FUNCTION(opcode);
+
+	switch (fillmode)
+	{
+		case ALTERNATE:
+			XSetFillRule(g_display, g_gc, EvenOddRule);
+			break;
+		case WINDING:
+			XSetFillRule(g_display, g_gc, WindingRule);
+			break;
+		default:
+			unimpl("fill mode %d\n", fillmode);
+	}
+
+	if (brush)
+		style = brush->style;
+	else
+		style = 0;
+
+	switch (style)
+	{
+		case 0:	/* Solid */
+			SET_FOREGROUND(fgcolour);
+			FILL_POLYGON((XPoint *) point, npoints);
+			break;
+
+		case 2:	/* Hatch */
+			fill = (Pixmap) ui_create_glyph(8, 8,
+							hatch_patterns + brush->pattern[0] * 8);
+			SET_FOREGROUND(fgcolour);
+			SET_BACKGROUND(bgcolour);
+			XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
+			XSetStipple(g_display, g_gc, fill);
+			XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+			FILL_POLYGON((XPoint *) point, npoints);
+			XSetFillStyle(g_display, g_gc, FillSolid);
+			XSetTSOrigin(g_display, g_gc, 0, 0);
+			ui_destroy_glyph((RD_HGLYPH) fill);
+			break;
+
+		case 3:	/* Pattern */
+			if (brush->bd == 0)	/* rdp4 brush */
+			{
+				for (i = 0; i != 8; i++)
+					ipattern[7 - i] = brush->pattern[i];
+				fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
+				SET_FOREGROUND(bgcolour);
+				SET_BACKGROUND(fgcolour);
+				XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
+				XSetStipple(g_display, g_gc, fill);
+				XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+				FILL_POLYGON((XPoint *) point, npoints);
+				XSetFillStyle(g_display, g_gc, FillSolid);
+				XSetTSOrigin(g_display, g_gc, 0, 0);
+				ui_destroy_glyph((RD_HGLYPH) fill);
+			}
+			else if (brush->bd->colour_code > 1)	/* > 1 bpp */
+			{
+				fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
+				XSetFillStyle(g_display, g_gc, FillTiled);
+				XSetTile(g_display, g_gc, fill);
+				XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+				FILL_POLYGON((XPoint *) point, npoints);
+				XSetFillStyle(g_display, g_gc, FillSolid);
+				XSetTSOrigin(g_display, g_gc, 0, 0);
+				ui_destroy_bitmap((RD_HBITMAP) fill);
+			}
+			else
+			{
+				fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
+				SET_FOREGROUND(bgcolour);
+				SET_BACKGROUND(fgcolour);
+				XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
+				XSetStipple(g_display, g_gc, fill);
+				XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+				FILL_POLYGON((XPoint *) point, npoints);
+				XSetFillStyle(g_display, g_gc, FillSolid);
+				XSetTSOrigin(g_display, g_gc, 0, 0);
+				ui_destroy_glyph((RD_HGLYPH) fill);
+			}
+			break;
+
+		default:
+			unimpl("brush %d\n", brush->style);
+	}
+
+	RESET_FUNCTION(opcode);
+}
+
+void
+ui_polyline(uint8 opcode,
+	    /* dest */ RD_POINT * points, int npoints,
+	    /* pen */ PEN * pen)
+{
+	/* TODO: set join style */
+	SET_FUNCTION(opcode);
+	SET_FOREGROUND(pen->colour);
+	XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
+	if (g_ownbackstore)
+		XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
+			   CoordModePrevious);
+
+	ON_ALL_SEAMLESS_WINDOWS(seamless_XDrawLines,
+				(sw->wnd, (XPoint *) points, npoints, sw->xoffset, sw->yoffset));
+
+	RESET_FUNCTION(opcode);
+}
+
+void
+ui_ellipse(uint8 opcode,
+	   /* mode */ uint8 fillmode,
+	   /* dest */ int x, int y, int cx, int cy,
+	   /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
+{
+	uint8 style, i, ipattern[8];
+	Pixmap fill;
+
+	SET_FUNCTION(opcode);
+
+	if (brush)
+		style = brush->style;
+	else
+		style = 0;
+
+	switch (style)
+	{
+		case 0:	/* Solid */
+			SET_FOREGROUND(fgcolour);
+			DRAW_ELLIPSE(x, y, cx, cy, fillmode);
+			break;
+
+		case 2:	/* Hatch */
+			fill = (Pixmap) ui_create_glyph(8, 8,
+							hatch_patterns + brush->pattern[0] * 8);
+			SET_FOREGROUND(fgcolour);
+			SET_BACKGROUND(bgcolour);
+			XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
+			XSetStipple(g_display, g_gc, fill);
+			XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+			DRAW_ELLIPSE(x, y, cx, cy, fillmode);
+			XSetFillStyle(g_display, g_gc, FillSolid);
+			XSetTSOrigin(g_display, g_gc, 0, 0);
+			ui_destroy_glyph((RD_HGLYPH) fill);
+			break;
+
+		case 3:	/* Pattern */
+			if (brush->bd == 0)	/* rdp4 brush */
+			{
+				for (i = 0; i != 8; i++)
+					ipattern[7 - i] = brush->pattern[i];
+				fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
+				SET_FOREGROUND(bgcolour);
+				SET_BACKGROUND(fgcolour);
+				XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
+				XSetStipple(g_display, g_gc, fill);
+				XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+				DRAW_ELLIPSE(x, y, cx, cy, fillmode);
+				XSetFillStyle(g_display, g_gc, FillSolid);
+				XSetTSOrigin(g_display, g_gc, 0, 0);
+				ui_destroy_glyph((RD_HGLYPH) fill);
+			}
+			else if (brush->bd->colour_code > 1)	/* > 1 bpp */
+			{
+				fill = (Pixmap) ui_create_bitmap(8, 8, brush->bd->data);
+				XSetFillStyle(g_display, g_gc, FillTiled);
+				XSetTile(g_display, g_gc, fill);
+				XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+				DRAW_ELLIPSE(x, y, cx, cy, fillmode);
+				XSetFillStyle(g_display, g_gc, FillSolid);
+				XSetTSOrigin(g_display, g_gc, 0, 0);
+				ui_destroy_bitmap((RD_HBITMAP) fill);
+			}
+			else
+			{
+				fill = (Pixmap) ui_create_glyph(8, 8, brush->bd->data);
+				SET_FOREGROUND(bgcolour);
+				SET_BACKGROUND(fgcolour);
+				XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
+				XSetStipple(g_display, g_gc, fill);
+				XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
+				DRAW_ELLIPSE(x, y, cx, cy, fillmode);
+				XSetFillStyle(g_display, g_gc, FillSolid);
+				XSetTSOrigin(g_display, g_gc, 0, 0);
+				ui_destroy_glyph((RD_HGLYPH) fill);
+			}
+			break;
+
+		default:
+			unimpl("brush %d\n", brush->style);
+	}
+
+	RESET_FUNCTION(opcode);
+}
+
+/* warning, this function only draws on wnd or backstore, not both */
+void
+ui_draw_glyph(int mixmode,
+	      /* dest */ int x, int y, int cx, int cy,
+	      /* src */ RD_HGLYPH glyph, int srcx, int srcy,
+	      int bgcolour, int fgcolour)
+{
+	SET_FOREGROUND(fgcolour);
+	SET_BACKGROUND(bgcolour);
+
+	XSetFillStyle(g_display, g_gc,
+		      (mixmode == MIX_TRANSPARENT) ? FillStippled : FillOpaqueStippled);
+	XSetStipple(g_display, g_gc, (Pixmap) glyph);
+	XSetTSOrigin(g_display, g_gc, x, y);
+
+	FILL_RECTANGLE_BACKSTORE(x, y, cx, cy);
+
+	XSetFillStyle(g_display, g_gc, FillSolid);
+}
+
+#define DO_GLYPH(ttext,idx) \
+{\
+  glyph = cache_get_font (font, ttext[idx]);\
+  if (!(flags & TEXT2_IMPLICIT_X))\
+  {\
+    xyoffset = ttext[++idx];\
+    if ((xyoffset & 0x80))\
+    {\
+      if (flags & TEXT2_VERTICAL)\
+        y += ttext[idx+1] | (ttext[idx+2] << 8);\
+      else\
+        x += ttext[idx+1] | (ttext[idx+2] << 8);\
+      idx += 2;\
+    }\
+    else\
+    {\
+      if (flags & TEXT2_VERTICAL)\
+        y += xyoffset;\
+      else\
+        x += xyoffset;\
+    }\
+  }\
+  if (glyph != NULL)\
+  {\
+    x1 = x + glyph->offset;\
+    y1 = y + glyph->baseline;\
+    XSetStipple(g_display, g_gc, (Pixmap) glyph->pixmap);\
+    XSetTSOrigin(g_display, g_gc, x1, y1);\
+    FILL_RECTANGLE_BACKSTORE(x1, y1, glyph->width, glyph->height);\
+    if (flags & TEXT2_IMPLICIT_X)\
+      x += glyph->width;\
+  }\
+}
+
+void
+ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y,
+	     int clipx, int clipy, int clipcx, int clipcy,
+	     int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
+	     int bgcolour, int fgcolour, uint8 * text, uint8 length)
+{
+	/* TODO: use brush appropriately */
+
+	FONTGLYPH *glyph;
+	int i, j, xyoffset, x1, y1;
+	DATABLOB *entry;
+
+	SET_FOREGROUND(bgcolour);
+
+	/* Sometimes, the boxcx value is something really large, like
+	   32691. This makes XCopyArea fail with Xvnc. The code below
+	   is a quick fix. */
+	if (boxx + boxcx > g_width)
+		boxcx = g_width - boxx;
+
+	if (boxcx > 1)
+	{
+		FILL_RECTANGLE_BACKSTORE(boxx, boxy, boxcx, boxcy);
+	}
+	else if (mixmode == MIX_OPAQUE)
+	{
+		FILL_RECTANGLE_BACKSTORE(clipx, clipy, clipcx, clipcy);
+	}
+
+	SET_FOREGROUND(fgcolour);
+	SET_BACKGROUND(bgcolour);
+	XSetFillStyle(g_display, g_gc, FillStippled);
+
+	/* Paint text, character by character */
+	for (i = 0; i < length;)
+	{
+		switch (text[i])
+		{
+			case 0xff:
+				/* At least two bytes needs to follow */
+				if (i + 3 > length)
+				{
+					warning("Skipping short 0xff command:");
+					for (j = 0; j < length; j++)
+						fprintf(stderr, "%02x ", text[j]);
+					fprintf(stderr, "\n");
+					i = length = 0;
+					break;
+				}
+				cache_put_text(text[i + 1], text, text[i + 2]);
+				i += 3;
+				length -= i;
+				/* this will move pointer from start to first character after FF command */
+				text = &(text[i]);
+				i = 0;
+				break;
+
+			case 0xfe:
+				/* At least one byte needs to follow */
+				if (i + 2 > length)
+				{
+					warning("Skipping short 0xfe command:");
+					for (j = 0; j < length; j++)
+						fprintf(stderr, "%02x ", text[j]);
+					fprintf(stderr, "\n");
+					i = length = 0;
+					break;
+				}
+				entry = cache_get_text(text[i + 1]);
+				if (entry->data != NULL)
+				{
+					if ((((uint8 *) (entry->data))[1] == 0)
+					    && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
+					{
+						if (flags & TEXT2_VERTICAL)
+							y += text[i + 2];
+						else
+							x += text[i + 2];
+					}
+					for (j = 0; j < entry->size; j++)
+						DO_GLYPH(((uint8 *) (entry->data)), j);
+				}
+				if (i + 2 < length)
+					i += 3;
+				else
+					i += 2;
+				length -= i;
+				/* this will move pointer from start to first character after FE command */
+				text = &(text[i]);
+				i = 0;
+				break;
+
+			default:
+				DO_GLYPH(text, i);
+				i++;
+				break;
+		}
+	}
+
+	XSetFillStyle(g_display, g_gc, FillSolid);
+
+	if (g_ownbackstore)
+	{
+		if (boxcx > 1)
+		{
+			XCopyArea(g_display, g_backstore, g_wnd, g_gc, boxx,
+				  boxy, boxcx, boxcy, boxx, boxy);
+			ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+						(g_display, g_backstore, sw->wnd, g_gc,
+						 boxx, boxy,
+						 boxcx, boxcy,
+						 boxx - sw->xoffset, boxy - sw->yoffset));
+		}
+		else
+		{
+			XCopyArea(g_display, g_backstore, g_wnd, g_gc, clipx,
+				  clipy, clipcx, clipcy, clipx, clipy);
+			ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+						(g_display, g_backstore, sw->wnd, g_gc,
+						 clipx, clipy,
+						 clipcx, clipcy, clipx - sw->xoffset,
+						 clipy - sw->yoffset));
+		}
+	}
+}
+
+void
+ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
+{
+	Pixmap pix;
+	XImage *image;
+
+	if (g_ownbackstore)
+	{
+		image = XGetImage(g_display, g_backstore, x, y, cx, cy, AllPlanes, ZPixmap);
+		exit_if_null(image);
+	}
+	else
+	{
+		pix = XCreatePixmap(g_display, g_wnd, cx, cy, g_depth);
+		XCopyArea(g_display, g_wnd, pix, g_gc, x, y, cx, cy, 0, 0);
+		image = XGetImage(g_display, pix, 0, 0, cx, cy, AllPlanes, ZPixmap);
+		exit_if_null(image);
+		XFreePixmap(g_display, pix);
+	}
+
+	offset *= g_bpp / 8;
+	cache_put_desktop(offset, cx, cy, image->bytes_per_line, g_bpp / 8, (uint8 *) image->data);
+
+	XDestroyImage(image);
+}
+
+void
+ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
+{
+	XImage *image;
+	uint8 *data;
+
+	offset *= g_bpp / 8;
+	data = cache_get_desktop(offset, cx, cy, g_bpp / 8);
+	if (data == NULL)
+		return;
+
+	image = XCreateImage(g_display, g_visual, g_depth, ZPixmap, 0,
+			     (char *) data, cx, cy, g_bpp, 0);
+
+	if (g_ownbackstore)
+	{
+		XPutImage(g_display, g_backstore, g_gc, image, 0, 0, x, y, cx, cy);
+		XCopyArea(g_display, g_backstore, g_wnd, g_gc, x, y, cx, cy, x, y);
+		ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+					(g_display, g_backstore, sw->wnd, g_gc,
+					 x, y, cx, cy, x - sw->xoffset, y - sw->yoffset));
+	}
+	else
+	{
+		XPutImage(g_display, g_wnd, g_gc, image, 0, 0, x, y, cx, cy);
+		ON_ALL_SEAMLESS_WINDOWS(XCopyArea,
+					(g_display, g_wnd, sw->wnd, g_gc, x, y, cx, cy,
+					 x - sw->xoffset, y - sw->yoffset));
+	}
+
+	XFree(image);
+}
+
+/* these do nothing here but are used in uiports */
+void
+ui_begin_update(void)
+{
+}
+
+void
+ui_end_update(void)
+{
+	XFlush(g_display);
+}
+
+
+void
+ui_seamless_begin(RD_BOOL hidden)
+{
+	if (!g_seamless_rdp)
+		return;
+
+	if (g_seamless_started)
+		return;
+
+	g_seamless_started = True;
+	g_seamless_hidden = hidden;
+
+	if (!hidden)
+		ui_seamless_toggle();
+
+	if (g_seamless_spawn_cmd[0])
+	{
+		seamless_send_spawn(g_seamless_spawn_cmd);
+		g_seamless_spawn_cmd[0] = 0;
+	}
+
+	seamless_send_persistent(g_seamless_persistent_mode);
+}
+
+
+void
+ui_seamless_end()
+{
+	/* Destroy all seamless windows */
+	while (g_seamless_windows)
+	{
+		XDestroyWindow(g_display, g_seamless_windows->wnd);
+		sw_remove_window(g_seamless_windows);
+	}
+
+	g_seamless_started = False;
+	g_seamless_active = False;
+	g_seamless_hidden = False;
+}
+
+
+void
+ui_seamless_hide_desktop()
+{
+	if (!g_seamless_rdp)
+		return;
+
+	if (!g_seamless_started)
+		return;
+
+	if (g_seamless_active)
+		ui_seamless_toggle();
+
+	g_seamless_hidden = True;
+}
+
+
+void
+ui_seamless_unhide_desktop()
+{
+	if (!g_seamless_rdp)
+		return;
+
+	if (!g_seamless_started)
+		return;
+
+	g_seamless_hidden = False;
+
+	ui_seamless_toggle();
+}
+
+
+void
+ui_seamless_toggle()
+{
+	if (!g_seamless_rdp)
+		return;
+
+	if (!g_seamless_started)
+		return;
+
+	if (g_seamless_hidden)
+		return;
+
+	if (g_seamless_active)
+	{
+		/* Deactivate */
+		while (g_seamless_windows)
+		{
+			XDestroyWindow(g_display, g_seamless_windows->wnd);
+			sw_remove_window(g_seamless_windows);
+		}
+		XMapWindow(g_display, g_wnd);
+	}
+	else
+	{
+		/* Activate */
+		XUnmapWindow(g_display, g_wnd);
+		seamless_send_sync();
+	}
+
+	g_seamless_active = !g_seamless_active;
+}
+
+
+void
+ui_seamless_create_window(unsigned long id, unsigned long group, unsigned long parent,
+			  unsigned long flags)
+{
+	Window wnd;
+	XSetWindowAttributes attribs;
+	XClassHint *classhints;
+	XSizeHints *sizehints;
+	XWMHints *wmhints;
+	long input_mask;
+	seamless_window *sw, *sw_parent;
+
+	if (!g_seamless_active)
+		return;
+
+	/* Ignore CREATEs for existing windows */
+	sw = sw_get_window_by_id(id);
+	if (sw)
+		return;
+
+	get_window_attribs(&attribs);
+	wnd = XCreateWindow(g_display, RootWindowOfScreen(g_screen), -1, -1, 1, 1, 0, g_depth,
+			    InputOutput, g_visual,
+			    CWBackPixel | CWBackingStore | CWColormap | CWBorderPixel, &attribs);
+
+	XStoreName(g_display, wnd, "SeamlessRDP");
+	ewmh_set_wm_name(wnd, "SeamlessRDP");
+
+	mwm_hide_decorations(wnd);
+
+	classhints = XAllocClassHint();
+	if (classhints != NULL)
+	{
+		classhints->res_name = "rdesktop";
+		classhints->res_class = "SeamlessRDP";
+		XSetClassHint(g_display, wnd, classhints);
+		XFree(classhints);
+	}
+
+	/* WM_NORMAL_HINTS */
+	sizehints = XAllocSizeHints();
+	if (sizehints != NULL)
+	{
+		sizehints->flags = USPosition;
+		XSetWMNormalHints(g_display, wnd, sizehints);
+		XFree(sizehints);
+	}
+
+	/* Parent-less transient windows */
+	if (parent == 0xFFFFFFFF)
+	{
+		XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
+		/* Some buggy wm:s (kwin) do not handle the above, so fake it
+		   using some other hints. */
+		ewmh_set_window_popup(wnd);
+	}
+	/* Normal transient windows */
+	else if (parent != 0x00000000)
+	{
+		sw_parent = sw_get_window_by_id(parent);
+		if (sw_parent)
+			XSetTransientForHint(g_display, wnd, sw_parent->wnd);
+		else
+			warning("ui_seamless_create_window: No parent window 0x%lx\n", parent);
+	}
+
+	if (flags & SEAMLESSRDP_CREATE_MODAL)
+	{
+		/* We do this to support buggy wm:s (*cough* metacity *cough*)
+		   somewhat at least */
+		if (parent == 0x00000000)
+			XSetTransientForHint(g_display, wnd, RootWindowOfScreen(g_screen));
+		ewmh_set_window_modal(wnd);
+	}
+
+	if (flags & SEAMLESSRDP_CREATE_TOPMOST)
+	{
+		/* Make window always-on-top */
+		ewmh_set_window_above(wnd);
+	}
+
+	/* FIXME: Support for Input Context:s */
+
+	get_input_mask(&input_mask);
+	input_mask |= PropertyChangeMask;
+
+	XSelectInput(g_display, wnd, input_mask);
+
+	/* handle the WM_DELETE_WINDOW protocol. */
+	XSetWMProtocols(g_display, wnd, &g_kill_atom, 1);
+
+	sw = xmalloc(sizeof(seamless_window));
+
+	memset(sw, 0, sizeof(seamless_window));
+
+	sw->wnd = wnd;
+	sw->id = id;
+	sw->group = sw_find_group(group, False);
+	sw->group->refcnt++;
+	sw->state = SEAMLESSRDP_NOTYETMAPPED;
+	sw->desktop = 0;
+	sw->position_timer = xmalloc(sizeof(struct timeval));
+	timerclear(sw->position_timer);
+
+	sw->outstanding_position = False;
+	sw->outpos_serial = 0;
+	sw->outpos_xoffset = sw->outpos_yoffset = 0;
+	sw->outpos_width = sw->outpos_height = 0;
+
+	sw->next = g_seamless_windows;
+	g_seamless_windows = sw;
+
+	/* WM_HINTS */
+	wmhints = XAllocWMHints();
+	if (wmhints)
+	{
+		wmhints->flags = WindowGroupHint;
+		wmhints->window_group = sw->group->wnd;
+		XSetWMHints(g_display, sw->wnd, wmhints);
+		XFree(wmhints);
+	}
+}
+
+
+void
+ui_seamless_destroy_window(unsigned long id, unsigned long flags)
+{
+	seamless_window *sw;
+
+	if (!g_seamless_active)
+		return;
+
+	sw = sw_get_window_by_id(id);
+	if (!sw)
+	{
+		warning("ui_seamless_destroy_window: No information for window 0x%lx\n", id);
+		return;
+	}
+
+	XDestroyWindow(g_display, sw->wnd);
+	sw_remove_window(sw);
+}
+
+
+void
+ui_seamless_destroy_group(unsigned long id, unsigned long flags)
+{
+	seamless_window *sw, *sw_next;
+
+	if (!g_seamless_active)
+		return;
+
+	for (sw = g_seamless_windows; sw; sw = sw_next)
+	{
+		sw_next = sw->next;
+
+		if (sw->group->id == id)
+		{
+			XDestroyWindow(g_display, sw->wnd);
+			sw_remove_window(sw);
+		}
+	}
+}
+
+
+void
+ui_seamless_seticon(unsigned long id, const char *format, int width, int height, int chunk,
+		    const char *data, int chunk_len)
+{
+	seamless_window *sw;
+
+	if (!g_seamless_active)
+		return;
+
+	sw = sw_get_window_by_id(id);
+	if (!sw)
+	{
+		warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
+		return;
+	}
+
+	if (chunk == 0)
+	{
+		if (sw->icon_size)
+			warning("ui_seamless_seticon: New icon started before previous completed\n");
+
+		if (strcmp(format, "RGBA") != 0)
+		{
+			warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
+			return;
+		}
+
+		sw->icon_size = width * height * 4;
+		if (sw->icon_size > 32 * 32 * 4)
+		{
+			warning("ui_seamless_seticon: Icon too large (%d bytes)\n", sw->icon_size);
+			sw->icon_size = 0;
+			return;
+		}
+
+		sw->icon_offset = 0;
+	}
+	else
+	{
+		if (!sw->icon_size)
+			return;
+	}
+
+	if (chunk_len > (sw->icon_size - sw->icon_offset))
+	{
+		warning("ui_seamless_seticon: Too large chunk received (%d bytes > %d bytes)\n",
+			chunk_len, sw->icon_size - sw->icon_offset);
+		sw->icon_size = 0;
+		return;
+	}
+
+	memcpy(sw->icon_buffer + sw->icon_offset, data, chunk_len);
+	sw->icon_offset += chunk_len;
+
+	if (sw->icon_offset == sw->icon_size)
+	{
+		ewmh_set_icon(sw->wnd, width, height, sw->icon_buffer);
+		sw->icon_size = 0;
+	}
+}
+
+
+void
+ui_seamless_delicon(unsigned long id, const char *format, int width, int height)
+{
+	seamless_window *sw;
+
+	if (!g_seamless_active)
+		return;
+
+	sw = sw_get_window_by_id(id);
+	if (!sw)
+	{
+		warning("ui_seamless_seticon: No information for window 0x%lx\n", id);
+		return;
+	}
+
+	if (strcmp(format, "RGBA") != 0)
+	{
+		warning("ui_seamless_seticon: Uknown icon format \"%s\"\n", format);
+		return;
+	}
+
+	ewmh_del_icon(sw->wnd, width, height);
+}
+
+
+void
+ui_seamless_move_window(unsigned long id, int x, int y, int width, int height, unsigned long flags)
+{
+	seamless_window *sw;
+
+	if (!g_seamless_active)
+		return;
+
+	sw = sw_get_window_by_id(id);
+	if (!sw)
+	{
+		warning("ui_seamless_move_window: No information for window 0x%lx\n", id);
+		return;
+	}
+
+	/* We ignore server updates until it has handled our request. */
+	if (sw->outstanding_position)
+		return;
+
+	if (!width || !height)
+		/* X11 windows must be at least 1x1 */
+		return;
+
+	/* If we move the window in a maximized state, then KDE won't
+	   accept restoration */
+	switch (sw->state)
+	{
+		case SEAMLESSRDP_MINIMIZED:
+		case SEAMLESSRDP_MAXIMIZED:
+			sw_update_position(sw);
+			return;
+	}
+
+	sw->xoffset = x;
+	sw->yoffset = y;
+	sw->width = width;
+	sw->height = height;
+
+	/* FIXME: Perhaps use ewmh_net_moveresize_window instead */
+	XMoveResizeWindow(g_display, sw->wnd, sw->xoffset, sw->yoffset, sw->width, sw->height);
+}
+
+
+void
+ui_seamless_restack_window(unsigned long id, unsigned long behind, unsigned long flags)
+{
+	seamless_window *sw;
+	XWindowChanges values;
+	unsigned long restack_serial;
+	unsigned int value_mask;
+
+	if (!g_seamless_active)
+		return;
+
+	sw = sw_get_window_by_id(id);
+	if (!sw)
+	{
+		warning("ui_seamless_restack_window: No information for window 0x%lx\n", id);
+		return;
+	}
+
+	if (behind)
+	{
+		seamless_window *sw_behind;
+
+		sw_behind = sw_get_window_by_id(behind);
+		if (!sw_behind)
+		{
+			warning("ui_seamless_restack_window: No information for behind window 0x%lx\n", behind);
+			return;
+		}
+
+		values.stack_mode = Below;
+		value_mask = CWStackMode | CWSibling;
+		values.sibling = sw_behind->wnd;
+
+		/* Avoid that topmost windows references non-topmost
+		   windows, and vice versa. */
+		if (ewmh_is_window_above(sw->wnd))
+		{
+			if (!ewmh_is_window_above(sw_behind->wnd))
+			{
+				/* Disallow, move to bottom of the
+				   topmost stack. */
+				values.stack_mode = Below;
+				value_mask = CWStackMode;	/* Not sibling */
+			}
+		}
+		else
+		{
+			if (ewmh_is_window_above(sw_behind->wnd))
+			{
+				/* Move to top of non-topmost
+				   stack. */
+				values.stack_mode = Above;
+				value_mask = CWStackMode;	/* Not sibling */
+			}
+		}
+	}
+	else
+	{
+		values.stack_mode = Above;
+		value_mask = CWStackMode;
+	}
+
+	restack_serial = XNextRequest(g_display);
+	XReconfigureWMWindow(g_display, sw->wnd, DefaultScreen(g_display), value_mask, &values);
+	sw_wait_configurenotify(sw->wnd, restack_serial);
+
+	sw_restack_window(sw, behind);
+
+	if (flags & SEAMLESSRDP_CREATE_TOPMOST)
+	{
+		/* Make window always-on-top */
+		ewmh_set_window_above(sw->wnd);
+	}
+}
+
+
+void
+ui_seamless_settitle(unsigned long id, const char *title, unsigned long flags)
+{
+	seamless_window *sw;
+
+	if (!g_seamless_active)
+		return;
+
+	sw = sw_get_window_by_id(id);
+	if (!sw)
+	{
+		warning("ui_seamless_settitle: No information for window 0x%lx\n", id);
+		return;
+	}
+
+	/* FIXME: Might want to convert the name for non-EWMH WMs */
+	XStoreName(g_display, sw->wnd, title);
+	ewmh_set_wm_name(sw->wnd, title);
+}
+
+
+void
+ui_seamless_setstate(unsigned long id, unsigned int state, unsigned long flags)
+{
+	seamless_window *sw;
+
+	if (!g_seamless_active)
+		return;
+
+	sw = sw_get_window_by_id(id);
+	if (!sw)
+	{
+		warning("ui_seamless_setstate: No information for window 0x%lx\n", id);
+		return;
+	}
+
+	switch (state)
+	{
+		case SEAMLESSRDP_NORMAL:
+		case SEAMLESSRDP_MAXIMIZED:
+			ewmh_change_state(sw->wnd, state);
+			XMapWindow(g_display, sw->wnd);
+			break;
+		case SEAMLESSRDP_MINIMIZED:
+			/* EWMH says: "if an Application asks to toggle _NET_WM_STATE_HIDDEN
+			   the Window Manager should probably just ignore the request, since
+			   _NET_WM_STATE_HIDDEN is a function of some other aspect of the window
+			   such as minimization, rather than an independent state." Besides,
+			   XIconifyWindow is easier. */
+			if (sw->state == SEAMLESSRDP_NOTYETMAPPED)
+			{
+				XWMHints *hints;
+				hints = XGetWMHints(g_display, sw->wnd);
+				if (hints)
+				{
+					hints->flags |= StateHint;
+					hints->initial_state = IconicState;
+					XSetWMHints(g_display, sw->wnd, hints);
+					XFree(hints);
+				}
+				XMapWindow(g_display, sw->wnd);
+			}
+			else
+				XIconifyWindow(g_display, sw->wnd, DefaultScreen(g_display));
+			break;
+		default:
+			warning("SeamlessRDP: Invalid state %d\n", state);
+			break;
+	}
+
+	sw->state = state;
+}
+
+
+void
+ui_seamless_syncbegin(unsigned long flags)
+{
+	if (!g_seamless_active)
+		return;
+
+	/* Destroy all seamless windows */
+	while (g_seamless_windows)
+	{
+		XDestroyWindow(g_display, g_seamless_windows->wnd);
+		sw_remove_window(g_seamless_windows);
+	}
+}
+
+
+void
+ui_seamless_ack(unsigned int serial)
+{
+	seamless_window *sw;
+	for (sw = g_seamless_windows; sw; sw = sw->next)
+	{
+		if (sw->outstanding_position && (sw->outpos_serial == serial))
+		{
+			sw->xoffset = sw->outpos_xoffset;
+			sw->yoffset = sw->outpos_yoffset;
+			sw->width = sw->outpos_width;
+			sw->height = sw->outpos_height;
+			sw->outstanding_position = False;
+
+			/* Do a complete redraw of the window as part of the
+			   completion of the move. This is to remove any
+			   artifacts caused by our lack of synchronization. */
+			XCopyArea(g_display, g_backstore,
+				  sw->wnd, g_gc,
+				  sw->xoffset, sw->yoffset, sw->width, sw->height, 0, 0);
+
+			break;
+		}
+	}
+}
