Package com.lixia.rdp.rdp5

Source Code of com.lixia.rdp.rdp5.ARDP5

/* JAlsRdp.java
* Component: ProperJavaRDP
*
* Revision: $Revision: 1.1.1.1 $
* Author: $Author: suvarov $
* Date: $Date: 2007/03/08 00:26:19 $
*
* Copyright (c) 2005 Propero Limited
*
* Purpose: JAlsRdp layer of communication
*/
package com.lixia.rdp.rdp5;

import com.alssoftrd.events.EventWakeUp;
import com.alssoftrd.utils.RDPConnection;
import com.lixia.rdp.Bitmap;
import com.lixia.rdp.Cache;
import com.lixia.rdp.CommunicationMonitor;
import com.lixia.rdp.ConnectionException;
import com.lixia.rdp.OrderException;
import com.lixia.rdp.OrdersJPanel;
import com.lixia.rdp.PstCache;
import com.lixia.rdp.RdesktopException;
import com.lixia.rdp.Secure;
import java.io.*;
import java.net.*;

import com.lixia.rdp.crypto.*;
import com.lixia.rdp.Package.RdpPackage;
import com.lixia.rdp.WrappedImage;
import com.lixia.rdp.rdp5.keys.KeysChannel;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.util.logging.Level;

public class ARDP5 {

    public static int RDP5_DISABLE_NOTHING = 0x00;

    public static int RDP5_NO_WALLPAPER = 0x01;

    public static int RDP5_NO_FULLWINDOWDRAG = 0x02;

    public static int RDP5_NO_MENUANIMATIONS = 0x04;

    public static int RDP5_NO_THEMING = 0x08;

    public static int RDP5_NO_CURSOR_SHADOW = 0x20;

    public static int RDP5_NO_CURSORSETTINGS = 0x40; /*
     * disables cursor
     * blinking
     */

//    protected static Logger logger = Logger.getLogger("RDP5");

    /* constants for RDP Layer */

    /* Info Packet Flags */
    private static final int INFO_MOUSE = 0x00000001;
    private static final int INFO_DISABLECTRLALTDEL = 0x00000002;
    private static final int INFO_AUTOLOGON = 0x00000008;
    private static final int INFO_UNICODE = 0x00000010;
    private static final int INFO_MAXIMIZESHELL = 0x00000020;
    private static final int INFO_LOGONNOTIFY = 0x00000040;
    private static final int INFO_COMPRESSION = 0x00000080;
    private static final int INFO_ENABLEWINDOWSKEY = 0x00000100;
    private static final int INFO_REMOTECONSOLEAUDIO = 0x00002000;
    private static final int INFO_FORCE_ENCRYPTED_CS_PDU = 0x00004000;
    private static final int INFO_RAIL = 0x00008000;
    private static final int INFO_LOGONERRORS = 0x00010000;
    private static final int INFO_MOUSE_HAS_WHEEL = 0x00020000;
    private static final int INFO_PASSWORD_IS_SC_PIN = 0x00040000;
    private static final int INFO_NOAUDIOPLAYBACK = 0x00080000;
    private static final int INFO_USING_SAVED_CREDS = 0x00100000;
    private static final int RNS_INFO_AUDIOCAPTURE = 0x00200000;
    private static final int RNS_INFO_VIDEO_DISABLE = 0x00400000;

    private static final int CompressionTypeMask = 0x00001E00;
    private static final int PACKET_COMPR_TYPE_8K = 0x00000100;
    private static final int PACKET_COMPR_TYPE_64K = 0x00000200;
    private static final int PACKET_COMPR_TYPE_RDP6 = 0x00000300;
    private static final int PACKET_COMPR_TYPE_RDP61 = 0x00000400;

    private static final int INFO_NORMALLOGON = (INFO_MOUSE | INFO_DISABLECTRLALTDEL | INFO_UNICODE | INFO_MAXIMIZESHELL);

    /* Extended Info Packet clientAddressFamily */
    private static final int CLIENT_INFO_AF_INET = 0x0002;
    private static final int CLIENT_INFO_AF_INET6 = 0x0017;

    // PDU Types
    private static final int RDP_PDU_DEMAND_ACTIVE = 1;

    private static final int RDP_PDU_CONFIRM_ACTIVE = 3;

    private static final int RDP_PDU_DEACTIVATE = 6;

    private static final int RDP_PDU_DATA = 7;

    // Data PDU Types
    private static final int RDP_DATA_PDU_UPDATE = 2;

    private static final int RDP_DATA_PDU_CONTROL = 20;

    private static final int RDP_DATA_PDU_POINTER = 27;

    private static final int RDP_DATA_PDU_INPUT = 28;

    private static final int RDP_DATA_PDU_SYNCHRONISE = 31;

    private static final int RDP_DATA_PDU_BELL = 34;

    private static final int RDP_DATA_PDU_LOGON = 38;

    private static final int RDP_DATA_PDU_FONT2 = 39;

    private static final int RDP_DATA_PDU_DISCONNECT = 47;

    // Control PDU types
    private static final int RDP_CTL_REQUEST_CONTROL = 1;

    private static final int RDP_CTL_GRANT_CONTROL = 2;

    private static final int RDP_CTL_DETACH = 3;

    private static final int RDP_CTL_COOPERATE = 4;

    // Update PDU Types
    private static final int RDP_UPDATE_ORDERS = 0;

    private static final int RDP_UPDATE_BITMAP = 1;

    private static final int RDP_UPDATE_PALETTE = 2;

    private static final int RDP_UPDATE_SYNCHRONIZE = 3;

    // Pointer PDU Types
    private static final int RDP_POINTER_SYSTEM = 1;

    private static final int RDP_POINTER_MOVE = 3;

    private static final int RDP_POINTER_COLOR = 6;

    private static final int RDP_POINTER_CACHED = 7;

    // System Pointer Types
    private static final int RDP_NULL_POINTER = 0;

    private static final int RDP_DEFAULT_POINTER = 0x7F00;

    // Input Devices
    private static final int RDP_INPUT_SYNCHRONIZE = 0;

    private static final int RDP_INPUT_CODEPOINT = 1;

    private static final int RDP_INPUT_VIRTKEY = 2;

    private static final int RDP_INPUT_SCANCODE = 4;

    private static final int RDP_INPUT_MOUSE = 0x8001;

    /* RDP capabilities */
    private static final int RDP_CAPSET_GENERAL = 1;

    private static final int RDP_CAPLEN_GENERAL = 0x18;

    private static final int OS_MAJOR_TYPE_UNIX = 4;

    private static final int OS_MINOR_TYPE_XSERVER = 7;

    private static final int RDP_CAPSET_BITMAP = 2;

    private static final int RDP_CAPLEN_BITMAP = 0x1C;

    private static final int RDP_CAPSET_ORDER = 3;

    private static final int RDP_CAPLEN_ORDER = 0x58;

    private static final int ORDER_CAP_NEGOTIATE = 2;

    private static final int ORDER_CAP_NOSUPPORT = 4;

    private static final int RDP_CAPSET_BMPCACHE = 4;

    private static final int RDP_CAPLEN_BMPCACHE = 0x28;

    private static final int RDP_CAPSET_CONTROL = 5;

    private static final int RDP_CAPLEN_CONTROL = 0x0C;

    private static final int RDP_CAPSET_ACTIVATE = 7;

    private static final int RDP_CAPLEN_ACTIVATE = 0x0C;

    private static final int RDP_CAPSET_POINTER = 8;

    private static final int RDP_CAPLEN_POINTER = 0x08;

    private static final int RDP_CAPSET_SHARE = 9;

    private static final int RDP_CAPLEN_SHARE = 0x08;

    private static final int RDP_CAPSET_COLCACHE = 10;

    private static final int RDP_CAPLEN_COLCACHE = 0x08;

    private static final int RDP_CAPSET_UNKNOWN = 13;

    private static final int RDP_CAPLEN_UNKNOWN = 0x9C;

    private static final int RDP_CAPSET_BMPCACHE2 = 19;

    private static final int RDP_CAPLEN_BMPCACHE2 = 0x28;

    private static final int BMPCACHE2_FLAG_PERSIST = (1 << 31);

    /* RDP bitmap cache (version 2) constants */
    public static final int BMPCACHE2_C0_CELLS = 0x78;

    public static final int BMPCACHE2_C1_CELLS = 0x78;

    public static final int BMPCACHE2_C2_CELLS = 0x150;

    public static final int BMPCACHE2_NUM_PSTCELLS = 0x9f6;

    private static final int RDP5_FLAG = 0x0030;

    private static final byte[] RDP_SOURCE = {(byte) 0x4D, (byte) 0x53,
        (byte) 0x54, (byte) 0x53, (byte) 0x43, (byte) 0x00}; // string
    // MSTSC
    // encoded
    // as 7 byte
    // US-Ascii

    public static WrappedImage wi;

    protected Secure SecureLayer = null;

    protected OrdersJPanel orders = null;

    public static Cache cache = null;

    private final Cursor g_null_cursor = null;

    private int next_packet = 0;

    private int rdp_shareid = 0;

    private boolean connected = false;

    private RdpPackage stream = null;

    public static KeysChannel keyChannel = null;

    /*
     * private final byte[] canned_caps = { (byte)0x01, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x09, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x04,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x0C, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0C, (byte)0x00, (byte)0x08,
     * (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0E,
     * (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00,
     * (byte)0x00, (byte)0x10, (byte)0x00, (byte)0x34, (byte)0x00, (byte)0xFE,
     * (byte)0x00, (byte)0x04, (byte)0x00, (byte)0xFE, (byte)0x00, (byte)0x04,
     * (byte)0x00, (byte)0xFE, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0xFE,
     * (byte)0x00, (byte)0x08, (byte)0x00, (byte)0xFE, (byte)0x00, (byte)0x10,
     * (byte)0x00, (byte)0xFE, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0xFE,
     * (byte)0x00, (byte)0x40, (byte)0x00, (byte)0xFE, (byte)0x00, (byte)0x80,
     * (byte)0x00, (byte)0xFE, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x40,
     * (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x00,
     * (byte)0x01, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00 };
     */
    private final byte[] canned_caps = {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, 0x0C, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0x00,
        0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x34, 0x00,
        (byte) 0xfe, 0x00, 0x04, 0x00, (byte) 0xfe, 0x00, 0x04, 0x00,
        (byte) 0xFE, 0x00, 0x08, 0x00, (byte) 0xFE, 0x00, 0x08, 0x00,
        (byte) 0xFE, 0x00, 0x10, 0x00, (byte) 0xFE, 0x00, 0x20, 0x00,
        (byte) 0xFE, 0x00, 0x40, 0x00, (byte) 0xFE, 0x00, (byte) 0x80,
        0x00, (byte) 0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00,
        0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00};

    static byte 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 byte caps_0x0c[] = {0x01, 0x00, 0x00, 0x00};

    static byte caps_0x0e[] = {0x01, 0x00, 0x00, 0x00};

    static byte caps_0x10[] = {(byte) 0xFE, 0x00, 0x04, 0x00, (byte) 0xFE,
        0x00, 0x04, 0x00, (byte) 0xFE, 0x00, 0x08, 0x00, (byte) 0xFE, 0x00,
        0x08, 0x00, (byte) 0xFE, 0x00, 0x10, 0x00, (byte) 0xFE, 0x00, 0x20,
        0x00, (byte) 0xFE, 0x00, 0x40, 0x00, (byte) 0xFE, 0x00,
        (byte) 0x80, 0x00, (byte) 0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
        0x08, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00};

    /**
     * Initialise RDP comms layer, and register virtual channels
     *
     * @param channels Virtual channels to be used in connection
     */
    public ARDP5(VChannels channels) {
        this.SecureLayer = new Secure(channels);
        ARDP5.cache = new Cache();
        RDPConnection.conf.secure = SecureLayer;
        this.orders = new OrdersJPanel();
        orders.registerCache(cache);
        wi = new WrappedImage(RDPConnection.conf.width, RDPConnection.conf.height, BufferedImage.TYPE_INT_RGB);
    }

    /**
     * Process a general capability set
     *
     * @param data Packet containing capability set data at current read
     * position
     */
    static void processGeneralCaps(RdpPackage data) {
        int pad2octetsB; /* rdp5 flags? */

        data.incrementPosition(10); // in_uint8s(s, 10);
        pad2octetsB = data.getLittleEndian16(); // in_uint16_le(s, pad2octetsB);

        if (pad2octetsB == 0) {
            RDPConnection.conf.use_rdp5 = false;
        }
    }

    /**
     * Process a bitmap capability set
     *
     * @param data Packet containing capability set data at current read
     * position
     */
    static void processBitmapCaps(RdpPackage data) {
        int width, height, depth;

        depth = data.getLittleEndian16(); // in_uint16_le(s, bpp);
        data.incrementPosition(6); // in_uint8s(s, 6);

        width = data.getLittleEndian16(); // in_uint16_le(s, width);
        height = data.getLittleEndian16(); // in_uint16_le(s, height);

//        logger.debug("setting desktop size and depth to: " + width + "x" + height + "x" + depth);
        /*
         * The server may limit bpp and change the size of the desktop (for
         * example when shadowing another session).
         */
        if (RDPConnection.conf.server_bpp != depth) {
//            logger.warn("colour depth changed from " + RDPConnection.conf.server_bpp + " to " + depth);
            RDPConnection.conf.set_bpp(depth);
        }
        if (RDPConnection.conf.width != width || RDPConnection.conf.height != height) {
//            logger.warn("screen size changed from " + RDPConnection.conf.width + "x" + RDPConnection.conf.height + " to " + width + "x" + height);
            RDPConnection.conf.width = width;
            RDPConnection.conf.height = height;
        }
    }

    /**
     * Process server capabilities
     *
     * @param data Packet containing capability set data at current read
     * position
     */
    void processServerCaps(RdpPackage data, int length) {
        int n;
        int next, start;
        int ncapsets, capset_type, capset_length;

        start = data.getPosition();

        ncapsets = data.getLittleEndian16(); // in_uint16_le(s, ncapsets);
        data.incrementPosition(2); // in_uint8s(s, 2); /* pad */

        for (n = 0; n < ncapsets; n++) {
            if (data.getPosition() > start + length) {
                return;
            }
            capset_type = data.getLittleEndian16(); // in_uint16_le(s,capset_type);
            capset_length = data.getLittleEndian16(); // in_uint16_le(s,capset_length);
            next = data.getPosition() + capset_length - 4;

            switch (capset_type) {
                case RDP_CAPSET_GENERAL:
                    processGeneralCaps(data);
                    break;
                case RDP_CAPSET_BITMAP:
                    processBitmapCaps(data);
                    break;
            }
            data.setPosition(next);
        }
    }

    /**
     * Process a disconnect PDU
     *
     * @param data Packet containing disconnect PDU at current read position
     * @return Code specifying the reason for disconnection
     */
    protected int processDisconnectPdu(RdpPackage data) {
//        logger.debug("Received disconnect PDU");
        return data.getLittleEndian32();
    }

    /**
     * Initialise a packet for sending data on the RDP layer
     *
     * @param size Size of RDP data
     * @return Packet initialised for RDP
     * @throws RdesktopException
     */
    private RdpPackage initData(int size) throws RdesktopException {
        RdpPackage buffer;

        buffer = SecureLayer.init(RDPConnection.conf.encryption ? Secure.SEC_ENCRYPT : 0, size + 18);
        buffer.pushLayer(RdpPackage.RDP_HEADER, 18);
        // buffer.setHeader(RdpPackage.RDP_HEADER);
        // buffer.incrementPosition(18);
        // buffer.setStart(buffer.getPosition());
        return buffer;
    }

    /**
     * Send a packet on the RDP layer
     *
     * @param data Packet to send
     * @param data_pdu_type Type of data
     * @throws RdesktopException
     * @throws IOException
     * @throws CryptoException
     */
    private void sendData(RdpPackage data, int data_pdu_type) throws RdesktopException, IOException, CryptoException {
        CommunicationMonitor.lock(this);

        int length;

        data.setPosition(data.getHeader(RdpPackage.RDP_HEADER));
        length = data.getEnd() - data.getPosition();

        data.setLittleEndian16(length);
        data.setLittleEndian16(RDP_PDU_DATA | 0x10);
        data.setLittleEndian16(SecureLayer.getUserID() + 1001);

        data.setLittleEndian32(this.rdp_shareid);
        data.set8(0); // pad
        data.set8(1); // stream id
        data.setLittleEndian16(length - 14);
        data.set8(data_pdu_type);
        data.set8(0); // compression type
        data.setLittleEndian16(0); // compression length

        SecureLayer.send(data, RDPConnection.conf.encryption ? Secure.SEC_ENCRYPT : 0);

        CommunicationMonitor.unlock(this);
    }

    /**
     * Receive a packet from the RDP layer
     *
     * @param type Type of PDU received, stored in type[0]
     * @return Packet received from RDP layer
     * @throws IOException
     * @throws RdesktopException
     * @throws CryptoException
     * @throws OrderException
     */
    private RdpPackage receive(int[] type) throws IOException, RdesktopException, CryptoException, OrderException {
        int length;

        if ((this.stream == null) || (this.next_packet >= this.stream.getEnd())) {
            this.stream = SecureLayer.receive();
            if (stream == null) {
                return null;
            }
            this.next_packet = this.stream.getPosition();
        } else {
            this.stream.setPosition(this.next_packet);
        }
        length = this.stream.getLittleEndian16();

        /* 32k packets are really 8, keepalive fix - rdesktop 1.2.0 */
        if (length == 0x8000) {
//            logger.warn("32k packet keepalive fix");
            next_packet += 8;
            type[0] = 0;
            return stream;
        }
        type[0] = this.stream.getLittleEndian16() & 0xf;
        if (stream.getPosition() != stream.getEnd()) {
            stream.incrementPosition(2);
        }
        this.next_packet += length;
        return stream;
    }

    /**
     * Connect to a server
     *
     * @param username Username for log on
     * @param server Server to connect to
     * @param domain Domain for log on
     * @param password Password for log on
     * @param command Alternative shell for session
     * @param directory Initial working directory for connection
     * @throws ConnectionException
     */
    public void connect(String username, InetAddress server, String domain, String password, String command, String directory) throws ConnectionException {
        int connect_flags = INFO_NORMALLOGON;

        if (RDPConnection.conf.bulk_compression) {
            connect_flags |= INFO_COMPRESSION | PACKET_COMPR_TYPE_64K;
        }
        if (RDPConnection.conf.autologin) {
            connect_flags |= INFO_AUTOLOGON;
        }
        if (RDPConnection.conf.console_audio) {
            connect_flags |= INFO_REMOTECONSOLEAUDIO;
        }

        connect_flags |= INFO_UNICODE;
        connect_flags |= INFO_LOGONERRORS;
        connect_flags |= INFO_LOGONNOTIFY;
        connect_flags |= INFO_ENABLEWINDOWSKEY;
        connect_flags |= RNS_INFO_AUDIOCAPTURE;

        try {
            SecureLayer.connect(server);
            this.connected = true;
            rdp_send_client_info(connect_flags, domain, username, password, command, directory);
        } // Handle an unresolvable hostname
        catch (UnknownHostException e) {
            throw new ConnectionException("Could not resolve host name: " + server);
        } // Handle a refused connection
        catch (ConnectException e) {
            throw new ConnectionException("Connection refused when trying to connect to " + server + " on port " + RDPConnection.conf.port);
        } // Handle a timeout on connecting
        catch (NoRouteToHostException e) {
            throw new ConnectionException("Connection timed out when attempting to connect to " + server);
        } catch (IOException e) {
            throw new ConnectionException("Connection Failed");
        } catch (RdesktopException ex) {
            java.util.logging.Logger.getLogger(ARDP5.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CryptoException ex) {
            java.util.logging.Logger.getLogger(ARDP5.class.getName()).log(Level.SEVERE, null, ex);
        } catch (OrderException ex) {
            java.util.logging.Logger.getLogger(ARDP5.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /**
     * Disconnect from an RDP session
     */
    public void disconnect() {
        this.connected = false;
        SecureLayer.disconnect();
    }

    /**
     * Retrieve status of connection
     *
     * @return True if connection to RDP session
     */
    public boolean isConnected() {
        return this.connected;
    }

    boolean deactivated;

    int ext_disc_reason;

    /**
     * RDP receive loop
     *
     * @param deactivated On return, stores true in deactivated[0] if the
     * session disconnected cleanly
     * @param ext_disc_reason On return, stores the reason for disconnection in
     * ext_disc_reason[0]
     * @throws IOException
     * @throws RdesktopException
     * @throws OrderException
     * @throws CryptoException
     */
    public void mainLoop(boolean[] deactivated, int[] ext_disc_reason) throws IOException, RdesktopException, OrderException, CryptoException {
        int[] type = new int[1];
        boolean disc = false; /* True when a disconnect PDU was received */

        boolean cont = true;

        RdpPackage data;

        while (cont) {
            try {
                data = this.receive(type);
                if (data == null) {
                    return;
                }
            } catch (EOFException e) {
                return;
            }
            switch (type[0]) {
                case (RDP_PDU_DEMAND_ACTIVE):
//                    logger.debug("Rdp.RDP_PDU_DEMAND_ACTIVE");
                    // get this after licence negotiation, just before the 1st
                    // order...
//                    NDC.push("processDemandActive");
                    this.processDemandActive(data);
                    // can use this to trigger things that have to be done before
                    // 1st order
//                    logger.debug("ready to send (got past licence negotiation)");
                    RDPConnection.conf.readytosend = true;
//                    NDC.pop();
                    deactivated[0] = false;
                    break;
                case (RDP_PDU_DEACTIVATE):
                    // get this on log off
                    deactivated[0] = true;
                    this.stream = null; // ty this fix
                    break;
                case (RDP_PDU_DATA):
                    // all the others should be this
//                    NDC.push("processData");
                    try {
                        disc = this.processData(data, ext_disc_reason);
                    } catch (RdesktopException ex) {
//                        logger.error(ex.getStackTrace());
                    } catch (OrderException ex) {
//                        logger.error(ex.getStackTrace());
                    }
//                    NDC.pop();
                    break;
                case 0:
                    break; // 32K keep alive fix, see receive() - rdesktop 1.2.0.
                default:
                    throw new RdesktopException("Unimplemented type in main loop :" + type[0]);
            }
            if (disc) {
                return;
            }
        }
    }

    private void rdp_out_client_timezone_info(RdpPackage data) {
        data.setLittleEndian16(0xffc4); // out_uint16_le(s, 0xffc4);
        data.setLittleEndian16(0xffff); // out_uint16_le(s, 0xffff);
        data.outUnicodeString("GTB, normaltid", 2 * "GTB, normaltid"
                .length()); // rdp_out_unistr(s, "GTB, normaltid", 2 *
        // strlen("GTB, normaltid"));
        data.incrementPosition(62 - 2 * "GTB, normaltid".length()); // out_uint8s(s,
        // 62 -
        // 2 *
        // strlen("GTB,
        // normaltid"));

        data.setLittleEndian32(0x0a0000); // out_uint32_le(s, 0x0a0000);
        data.setLittleEndian32(0x050000); // out_uint32_le(s, 0x050000);
        data.setLittleEndian32(3); // out_uint32_le(s, 3);
        data.setLittleEndian32(0); // out_uint32_le(s, 0);
        data.setLittleEndian32(0); // out_uint32_le(s, 0);

        data.outUnicodeString("GTB, sommartid", 2 * "GTB, sommartid"
                .length()); // rdp_out_unistr(s, "GTB, sommartid", 2 *
        // strlen("GTB, sommartid"));
        data.incrementPosition(62 - 2 * "GTB, sommartid".length()); // out_uint8s(s,
        // 62 -
        // 2 *
        // strlen("GTB,
        // sommartid"));

        data.setLittleEndian32(0x30000); // out_uint32_le(s, 0x30000);
        data.setLittleEndian32(0x050000); // out_uint32_le(s, 0x050000);
    }

    /**
     * Send user logon details to the server
     *
     * @param flags Set of flags defining logon type
     * @param domain Domain for logon
     * @param username Username for logon
     * @param password Password for logon
     * @param command Alternative shell for session
     * @param directory Starting working directory for session
     * @throws RdesktopException
     * @throws IOException
     * @throws CryptoException
     */
    private void rdp_send_client_info(int flags, String domain, String username, String password, String command, String directory) throws RdesktopException, IOException, CryptoException {
        int len_ip = 2 * "127.0.0.1".length();
        int len_dll = 2 * "C:\\WINNT\\System32\\mstscax.dll".length();
        int packetlen;

        int sec_flags = Secure.SEC_INFO_PKT | (RDPConnection.conf.encryption ? Secure.SEC_ENCRYPT : 0);
        int domainlen = 2 * domain.length();
        int userlen = 2 * username.length();
        int passlen = 2 * password.length();
        int commandlen = 2 * command.length();
        int dirlen = 2 * directory.length();

        packetlen = 8 + (5 * 4) + domainlen + userlen + passlen + commandlen + dirlen;
        if (RDPConnection.conf.use_rdp5 && 1 != RDPConnection.conf.server_rdp_version) {
            //rdp 5
            packetlen += 180 + (2 * 4) + len_ip + len_dll;
        }
        RdpPackage data = SecureLayer.init(sec_flags, packetlen);

        data.setLittleEndian32(0);/* codePage */

        data.setLittleEndian32(flags);/* flags */

        data.setLittleEndian16(domainlen);
        data.setLittleEndian16(userlen);
        data.setLittleEndian16(passlen);
        data.setLittleEndian16(commandlen);
        data.setLittleEndian16(dirlen);
        data.outUnicodeString(domain, domainlen);
        data.outUnicodeString(username, userlen);
        data.outUnicodeString(password, passlen);
        data.outUnicodeString(command, commandlen);
        data.outUnicodeString(directory, dirlen);

        if (RDPConnection.conf.use_rdp5 && 1 != RDPConnection.conf.server_rdp_version) {
//            logger.debug("Sending RDP5-style Logon packet");

            data.setLittleEndian16(CLIENT_INFO_AF_INET);
            data.setLittleEndian16(len_ip + 2);
            // // Length of client ip
            data.outUnicodeString("127.0.0.1", len_ip);
            data.setLittleEndian16(len_dll + 2);
            data.outUnicodeString("C:\\WINNT\\System32\\mstscax.dll", len_dll);

            /* clientTimeZone (172 bytes) */
            rdp_out_client_timezone_info(data);

            data.setLittleEndian32(2); // out_uint32_le(s, 2);
            data.setLittleEndian32(0); // out_uint32(s, 0);
//            data.setLittleEndian32(0xffffffc4); // out_uint32_le(s, 0xffffffc4);
//            data.setLittleEndian32(0xfffffffe); // out_uint32_le(s, 0xfffffffe);
            data.setLittleEndian32(RDPConnection.conf.rdp5_performanceflags); // out_uint32_le(s,
            // 0x0f);
            data.setLittleEndian32(0); // out_uint32(s, 0);
        }

        data.markEnd();
        byte[] buffer = new byte[data.getEnd()];
        data.copyToByteArray(buffer, 0, 0, data.getEnd());
        SecureLayer.send(data, sec_flags);
    }

    /**
     * Process an activation demand from the server (received between licence
     * negotiation and 1st order)
     *
     * @param data Packet containing demand at current read position
     * @throws RdesktopException
     * @throws IOException
     * @throws CryptoException
     * @throws OrderException
     */
    private void processDemandActive(RdpPackage data)
            throws RdesktopException, IOException, CryptoException,
            OrderException {
        int type[] = new int[1];
        int len_src_descriptor, len_combined_caps;

        this.rdp_shareid = data.getLittleEndian32();
        len_src_descriptor = data.getLittleEndian16();
        len_combined_caps = data.getLittleEndian16();
        data.incrementPosition(len_src_descriptor);
        processServerCaps(data, len_combined_caps);

        this.sendConfirmActive();

        this.sendSynchronize();
        this.sendControl(RDP_CTL_COOPERATE);
        this.sendControl(RDP_CTL_REQUEST_CONTROL);

        this.receive(type); // Receive RDP_PDU_SYNCHRONIZE
        this.receive(type); // Receive RDP_CTL_COOPERATE
        this.receive(type); // Receive RDP_CTL_GRANT_CONTROL

        this.sendInput(0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0);
        this.sendFonts(1);
        this.sendFonts(2);

        this.receive(type); // Receive an unknown PDU Code = 0x28

        this.orders.resetOrderState();
    }

    /**
     * Process a data PDU received from the server
     *
     * @param data Packet containing data PDU at current read position
     * @param ext_disc_reason If a disconnect PDU is received, stores
     * disconnection reason at ext_disc_reason[0]
     * @return True if disconnect PDU was received
     * @throws RdesktopException
     * @throws OrderException
     */
    private boolean processData(RdpPackage data, int[] ext_disc_reason) throws RdesktopException, OrderException {
        @SuppressWarnings("unused")
        int data_type, ctype, clen, len, roff, rlen;

        data.incrementPosition(6); // skip shareid, pad, streamid
        len = data.getLittleEndian16();
        data_type = data.get8();
        ctype = data.get8(); // compression type
        clen = data.getLittleEndian16(); // compression length
        clen -= 18;

        switch (data_type) {
            case (RDP_DATA_PDU_UPDATE):
//                logger.debug("Rdp.RDP_DATA_PDU_UPDATE");
                this.processUpdate(data);
                break;
            case RDP_DATA_PDU_CONTROL:
//                logger.debug(("Received Control PDU\n"));
                break;
            case RDP_DATA_PDU_SYNCHRONISE:
//                logger.debug(("Received Sync PDU\n"));
                break;

            case (RDP_DATA_PDU_POINTER):
//                logger.debug("Received pointer PDU");
                this.processPointer(data);
                break;
            case (RDP_DATA_PDU_BELL):
//                logger.debug("Received bell PDU");
                Toolkit tx = Toolkit.getDefaultToolkit();
                tx.beep();
                break;
            case (RDP_DATA_PDU_LOGON):
//                logger.debug("User logged on");
                RDPConnection.conf.loggedon = true;
                break;
            case RDP_DATA_PDU_DISCONNECT:
                /*
                 * Normally received when user logs out or disconnects from a
                 * console session on Windows XP and 2003 Server
                 */
                ext_disc_reason[0] = processDisconnectPdu(data);
//                logger.info("Received disconnect PDU");
                if (RDPConnection.conf.loggedon || ext_disc_reason[0] > 0) {
                    return true;
                }
                break;
            default:
//                logger.warn("Unimplemented Data PDU type " + data_type);
        }
        return false;
    }

    private void processUpdate(RdpPackage data) throws OrderException, RdesktopException {
        int update_type;
        update_type = data.getLittleEndian16();

        switch (update_type) {
            case (RDP_UPDATE_ORDERS):
                data.incrementPosition(2); // pad
                int n_orders = data.getLittleEndian16();
                data.incrementPosition(2); // pad
                this.orders.processOrders(data, next_packet, n_orders);
                break;
            case (RDP_UPDATE_BITMAP):
                this.processBitmapUpdates(data);
                break;
            case (RDP_UPDATE_PALETTE):
                this.processPalette(data);
                break;
            case (RDP_UPDATE_SYNCHRONIZE):
                break;
            default:
//                logger.warn("Unimplemented Update type " + update_type);
        }
    }

    private void sendConfirmActive() throws RdesktopException, IOException, CryptoException {
        int caplen = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER
                + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE
                + RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL + RDP_CAPLEN_POINTER
                + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4; // this is a fix
        // for W2k.
        // Purpose
        // unknown

        int sec_flags = RDPConnection.conf.encryption ? (RDP5_FLAG | Secure.SEC_ENCRYPT) : RDP5_FLAG;

        RdpPackage data = SecureLayer.init(sec_flags, 6 + 14 + caplen + RDP_SOURCE.length);

        // RdpPackage data = this.init(14 + caplen +
        // RDP_SOURCE.length);
        data.setLittleEndian16(2 + 14 + caplen + RDP_SOURCE.length);
        data.setLittleEndian16((RDP_PDU_CONFIRM_ACTIVE | 0x10));
        data.setLittleEndian16(RDPConnection.conf.mcs.getUserID() /* McsUserID() */ + 1001);

        data.setLittleEndian32(this.rdp_shareid);
        data.setLittleEndian16(0x3ea); // user id
        data.setLittleEndian16(RDP_SOURCE.length);
        data.setLittleEndian16(caplen);

        data.copyFromByteArray(RDP_SOURCE, 0, data.getPosition(),
                RDP_SOURCE.length);
        data.incrementPosition(RDP_SOURCE.length);
        data.setLittleEndian16(0xd); // num_caps
        data.incrementPosition(2); // pad

        this.sendGeneralCaps(data);
        // ta.incrementPosition(this.RDP_CAPLEN_GENERAL);
        this.sendBitmapCaps(data);
        this.sendOrderCaps(data);

//        if (RDPConnection.conf.use_rdp5 && RDPConnection.conf.persistent_bitmap_caching) {
        if (RDPConnection.conf.use_rdp5) {
//            logger.info("Persistent caching enabled");
            this.sendBitmapcache2Caps(data);
        } else {
            this.sendBitmapcacheCaps(data);
        }

        this.sendColorcacheCaps(data);
        this.sendActivateCaps(data);
        this.sendControlCaps(data);
        this.sendPointerCaps(data);
        this.sendShareCaps(data);
        // this.sendUnknownCaps(data);

        this.sendUnknownCaps(data, 0x0d, 0x58, caps_0x0d); // rdp_out_unknown_caps(s,
        // 0x0d, 0x58,
        // caps_0x0d); /*
        // international? */
        this.sendUnknownCaps(data, 0x0c, 0x08, caps_0x0c); // rdp_out_unknown_caps(s,
        // 0x0c, 0x08,
        // caps_0x0c);
        this.sendUnknownCaps(data, 0x0e, 0x08, caps_0x0e); // rdp_out_unknown_caps(s,
        // 0x0e, 0x08,
        // caps_0x0e);
        this.sendUnknownCaps(data, 0x10, 0x34, caps_0x10); // rdp_out_unknown_caps(s,
        // 0x10, 0x34,
        // caps_0x10); /*
        // glyph cache? */

        data.markEnd();
//        logger.debug("confirm active");
        // this.send(data, RDP_PDU_CONFIRM_ACTIVE);
        RDPConnection.conf.secure.send(data, sec_flags);
    }

    private void sendGeneralCaps(RdpPackage data) {
        data.setLittleEndian16(RDP_CAPSET_GENERAL);
        data.setLittleEndian16(RDP_CAPLEN_GENERAL);
        data.setLittleEndian16(1); /* OS major type */

        data.setLittleEndian16(3); /* OS minor type */

        data.setLittleEndian16(0x200); /* Protocol version */

        data.setLittleEndian16(0); /* Compression types */

        data.setLittleEndian16(0); /* Pad */

        data.setLittleEndian16(RDPConnection.conf.use_rdp5 ? 0x40d : 0);
        // data.setLittleEndian16(RDPConnection.conf.use_rdp5 ? 0x1d04 : 0); // this seems
        /*
         * 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..
         */
        data.setLittleEndian16(0); /* Update capability */

        data.setLittleEndian16(0); /* Remote unshare capability */

        data.setLittleEndian16(0); /* Compression level */

        data.setLittleEndian16(0); /* Pad */

    }

    private void sendBitmapCaps(RdpPackage data) {
        data.setLittleEndian16(RDP_CAPSET_BITMAP);
        data.setLittleEndian16(RDP_CAPLEN_BITMAP);
        data.setLittleEndian16(RDPConnection.conf.server_bpp); /* Preferred BPP */

        data.setLittleEndian16(1); /* Receive 1 BPP */

        data.setLittleEndian16(1); /* Receive 4 BPP */

        data.setLittleEndian16(1); /* Receive 8 BPP */

        data.setLittleEndian16(RDPConnection.conf.width); /* Desktop width */

        data.setLittleEndian16(RDPConnection.conf.height); /* Desktop height */

        data.setLittleEndian16(0); /* Pad */

        data.setLittleEndian16(1); /* Allow resize */

        data.setLittleEndian16(RDPConnection.conf.bitmap_compression ? 1 : 0); /*
         * Support
         * compression
         */

        data.setLittleEndian16(0); /* Unknown */

        data.setLittleEndian16(1); /* Unknown */

        data.setLittleEndian16(0); /* Pad */

    }

    private void sendOrderCaps(RdpPackage data) {
        byte[] order_caps = new byte[32];
        order_caps[0] = 1; /* dest blt */

        order_caps[1] = 1; /* pat blt */// nb no rectangle orders if this is 0

        order_caps[2] = 1; /* screen blt */

        order_caps[3] = (byte) (RDPConnection.conf.bitmap_caching ? 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] = (byte) (RDPConnection.conf.desktop_save ? 1 : 0); /* desksave */

        order_caps[13] = 1; /* memblt */

        order_caps[14] = 1; /* triblt */

        order_caps[20] = (byte) (RDPConnection.conf.polygon_ellipse_orders ? 1 : 0); /* polygon */

        order_caps[21] = (byte) (RDPConnection.conf.polygon_ellipse_orders ? 1 : 0); /* polygon2 */

        order_caps[22] = 1; /* polyline */

        order_caps[25] = (byte) (RDPConnection.conf.polygon_ellipse_orders ? 1 : 0); /* ellipse */

        order_caps[26] = (byte) (RDPConnection.conf.polygon_ellipse_orders ? 1 : 0); /* ellipse2 */

        order_caps[27] = 1; /* text2 */

        data.setLittleEndian16(RDP_CAPSET_ORDER);
        data.setLittleEndian16(RDP_CAPLEN_ORDER);
        data.incrementPosition(20); /* Terminal desc, pad */

        data.setLittleEndian16(1); /* Cache X granularity */

        data.setLittleEndian16(20); /* Cache Y granularity */

        data.setLittleEndian16(0); /* Pad */

        data.setLittleEndian16(1); /* Max order level */

        data.setLittleEndian16(0x147); /* Number of fonts */

        data.setLittleEndian16(0x2a); /* Capability flags */

        data.copyFromByteArray(order_caps, 0, data.getPosition(), 32); /*
         * Orders
         * supported
         */

        data.incrementPosition(32);
        data.setLittleEndian16(0x6a1); /* Text capability flags */

        data.incrementPosition(6); /* Pad */

        data.setLittleEndian32(RDPConnection.conf.desktop_save ? 0x38400 : 0); /*
         * Desktop
         * cache
         * size
         */

        data.setLittleEndian32(0); /* Unknown */

        data.setLittleEndian32(0x4e4); /* Unknown */

    }

    private void sendBitmapcacheCaps(RdpPackage data) {
        data.setLittleEndian16(RDP_CAPSET_BMPCACHE);
        data.setLittleEndian16(RDP_CAPLEN_BMPCACHE);
        data.incrementPosition(24); /* unused */

        data.setLittleEndian16(0x258); /* entries */

        data.setLittleEndian16(0x100); /* max cell size */

        data.setLittleEndian16(0x12c); /* entries */

        data.setLittleEndian16(0x400); /* max cell size */

        data.setLittleEndian16(0x106); /* entries */

        data.setLittleEndian16(0x1000); /* max cell size */

    }

    /* Output bitmap cache v2 capability set */
    private void sendBitmapcache2Caps(RdpPackage data) {
        data.setLittleEndian16(RDP_CAPSET_BMPCACHE2); // out_uint16_le(s,RDP_CAPSET_BMPCACHE2);
        data.setLittleEndian16(RDP_CAPLEN_BMPCACHE2); // out_uint16_le(s,RDP_CAPLEN_BMPCACHE2);
        data.setLittleEndian16(RDPConnection.conf.persistent_bitmap_caching ? 2 : 0); /* version */

        data.setBigEndian16(3); /* number of caches in this set */
        /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */

        data.setLittleEndian32(BMPCACHE2_C0_CELLS); // out_uint32_le(s,BMPCACHE2_C0_CELLS);
        data.setLittleEndian32(BMPCACHE2_C1_CELLS); // out_uint32_le(s,BMPCACHE2_C1_CELLS);
        // data.setLittleEndian32(PstCache.pstcache_init(2) ?
        // (BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST) :
        // BMPCACHE2_C2_CELLS);
        if (PstCache.pstcache_init(2)) {
//            logger.info("Persistent cache initialized");
            data.setLittleEndian32(BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
        } else {
//            logger.info("Persistent cache not initialized");
            data.setLittleEndian32(BMPCACHE2_C2_CELLS);
        }
        data.incrementPosition(20); // out_uint8s(s, 20); /* other bitmap caches not used */
    }

    private void sendColorcacheCaps(RdpPackage data) {
        data.setLittleEndian16(RDP_CAPSET_COLCACHE);
        data.setLittleEndian16(RDP_CAPLEN_COLCACHE);
        data.setLittleEndian16(6); /* cache size */

        data.setLittleEndian16(0); /* pad */

    }

    private void sendActivateCaps(RdpPackage data) {
        data.setLittleEndian16(RDP_CAPSET_ACTIVATE);
        data.setLittleEndian16(RDP_CAPLEN_ACTIVATE);
        data.setLittleEndian16(0); /* Help key */

        data.setLittleEndian16(0); /* Help index key */

        data.setLittleEndian16(0); /* Extended help key */

        data.setLittleEndian16(0); /* Window activate */

    }

    private void sendControlCaps(RdpPackage data) {
        data.setLittleEndian16(RDP_CAPSET_CONTROL);
        data.setLittleEndian16(RDP_CAPLEN_CONTROL);
        data.setLittleEndian16(0); /* Control capabilities */

        data.setLittleEndian16(0); /* Remote detach */

        data.setLittleEndian16(2); /* Control interest */

        data.setLittleEndian16(2); /* Detach interest */

    }

    private void sendPointerCaps(RdpPackage data) {
        data.setLittleEndian16(RDP_CAPSET_POINTER);
        data.setLittleEndian16(RDP_CAPLEN_POINTER);
        data.setLittleEndian16(0); /* Colour pointer */

        data.setLittleEndian16(20); /* Cache size */

    }

    private void sendShareCaps(RdpPackage data) {
        data.setLittleEndian16(RDP_CAPSET_SHARE);
        data.setLittleEndian16(RDP_CAPLEN_SHARE);
        data.setLittleEndian16(0); /* userid */

        data.setLittleEndian16(0); /* pad */

    }

    private void sendUnknownCaps(RdpPackage data, int id, int length, byte[] caps) {
        data.setLittleEndian16(id /* RDP_CAPSET_UNKNOWN */);
        data.setLittleEndian16(length /* 0x58 */);
        data.copyFromByteArray(caps, 0, data.getPosition(), /* RDP_CAPLEN_UNKNOWN */ length - 4);
        data.incrementPosition(/* RDP_CAPLEN_UNKNOWN */length - 4);
    }

    private void sendSynchronize() throws RdesktopException, IOException, CryptoException {
        RdpPackage data = this.initData(4);
        data.setLittleEndian16(1); // type
        data.setLittleEndian16(1002);
        data.markEnd();
//        logger.debug("sync");
        this.sendData(data, RDP_DATA_PDU_SYNCHRONISE);
    }

    private void sendControl(int action) throws RdesktopException, IOException, CryptoException {
        RdpPackage data = this.initData(8);
        data.setLittleEndian16(action);
        data.setLittleEndian16(0); // userid
        data.setLittleEndian32(0); // control id
        data.markEnd();
//        logger.debug("control");
        this.sendData(data, RDP_DATA_PDU_CONTROL);
    }

    public void sendInput(int time, int message_type, int device_flags, int param1, int param2) {
        RdpPackage data = null;
        try {
            data = this.initData(16);
        } catch (RdesktopException e) {
        }

        data.setLittleEndian16(1); /* number of events */

        data.setLittleEndian16(0); /* pad */

        data.setLittleEndian32(time);
        data.setLittleEndian16(message_type);
        data.setLittleEndian16(device_flags);
        data.setLittleEndian16(param1);
        data.setLittleEndian16(param2);
        data.markEnd();
        // logger.info("input");
        // if(logger.isInfoEnabled()) logger.info(data);
        try {
            this.sendData(data, RDP_DATA_PDU_INPUT);
        } catch (RdesktopException r) {
            if (RDPConnection.conf.rdp.isConnected()) {
            }
            RDPConnection.conf.exit();
        } catch (IOException ex) {
            if (RDPConnection.conf.rdp.isConnected()) {
            }
            RDPConnection.conf.exit();
        } catch (CryptoException ex) {
            if (RDPConnection.conf.rdp.isConnected()) {
            }
            RDPConnection.conf.exit();
        }
    }

    private void sendFonts(int seq) throws RdesktopException, IOException, CryptoException {
        RdpPackage data = this.initData(8);
        data.setLittleEndian16(0); /* number of fonts */

        data.setLittleEndian16(0x3e); /* unknown */

        data.setLittleEndian16(seq); /* unknown */

        data.setLittleEndian16(0x32); /* entry size */

        data.markEnd();
//        logger.debug("fonts");
        this.sendData(data, RDP_DATA_PDU_FONT2);
    }

    private void processPointer(RdpPackage data) throws RdesktopException {
        int message_type;
        int x = 0, y = 0;

        message_type = data.getLittleEndian16();
        data.incrementPosition(2);
        switch (message_type) {
            case (RDP_POINTER_MOVE):
//                logger.debug("Rdp.RDP_POINTER_MOVE");
                x = data.getLittleEndian16();
                y = data.getLittleEndian16();
                if (data.getPosition() <= data.getEnd()) {
                    // Nothing to do
//                    surface.movePointer(x, y);
                }
                break;
            case (RDP_POINTER_COLOR):
                process_colour_pointer_pdu(data);
                break;
            case (RDP_POINTER_CACHED):
                process_cached_pointer_pdu(data);
                break;
            case RDP_POINTER_SYSTEM:
                // Esto pone el mouse en el centro.
//                process_system_pointer_pdu(data);
                break;
            default:
                break;
        }
    }

    private void process_system_pointer_pdu(RdpPackage data) {
        int system_pointer_type = 0;

        data.getLittleEndian16(system_pointer_type); // in_uint16(s,
        // system_pointer_type);
        switch (system_pointer_type) {
            case RDP_NULL_POINTER:
//                logger.debug("RDP_NULL_POINTER");
                break;
            default:
//                logger.warn("Unimplemented system pointer message 0x" + Integer.toHexString(system_pointer_type));
            // unimpl("System pointer message 0x%x\n", system_pointer_type);
        }
    }

    protected void processBitmapUpdates(RdpPackage data) throws RdesktopException {
//        logger.info("processBitmapUpdates");
        int n_updates;
        int left, top, right, bottom, width, height;
        int cx, cy, bitsperpixel, compression, buffersize, size;
        byte[] pixel;

        int minX, minY, maxX, maxY;

        maxX = maxY = 0;
        minX = RDPConnection.conf.width;
        minY = RDPConnection.conf.height;

        n_updates = data.getLittleEndian16();

        for (int i = 0; i < n_updates; i++) {
            left = data.getLittleEndian16();
            top = data.getLittleEndian16();
            right = data.getLittleEndian16();
            bottom = data.getLittleEndian16();
            width = data.getLittleEndian16();
            height = data.getLittleEndian16();
            bitsperpixel = data.getLittleEndian16();
            int Bpp = (bitsperpixel + 7) / 8;
            compression = data.getLittleEndian16();
            buffersize = data.getLittleEndian16();

            cx = right - left + 1;
            cy = bottom - top + 1;

            if (minX > left) {
                minX = left;
            }
            if (minY > top) {
                minY = top;
            }
            if (maxX < right) {
                maxX = right;
            }
            if (maxY < bottom) {
                maxY = bottom;
            }
            /* Server may limit bpp - this is how we find out */
            if (RDPConnection.conf.server_bpp != bitsperpixel) {
//                logger.warn("Server limited colour depth to " + bitsperpixel + " bits");
                RDPConnection.conf.set_bpp(bitsperpixel);
            }
            if (compression == 0) {
                pixel = new byte[width * height * Bpp];
                for (int y = 0; y < height; y++) {
                    data.copyToByteArray(pixel, (height - y - 1) * (width * Bpp), data.getPosition(), width * Bpp);
                    data.incrementPosition(width * Bpp);
                }
                wi.setRGB(left, top, cx, cy, Bitmap.convertImage(pixel, Bpp), 0, width);
                EventWakeUp.getInstance().imageSegmented(left, top, ARDP5.wi.getSubimage(left, top, cx, cy));
                continue;
            }
            if ((compression & 0x400) != 0) {
                size = buffersize;
            } else {
                data.incrementPosition(2); // pad
                size = data.getLittleEndian16();
                data.incrementPosition(4); // line size, final size
            }
            if (Bpp == 1) {
                pixel = Bitmap.decompress(width, height, size, data, Bpp);
                if (pixel != null) {
                    wi.setRGB(left, top, cx, cy, Bitmap.convertImage(pixel, Bpp), 0, width);
                    EventWakeUp.getInstance().imageSegmented(left, top, ARDP5.wi.getSubimage(left, top, cx, cy));
                } else {
//                    logger.warn("Could not decompress bitmap");
                }
            } else {
                if (RDPConnection.conf.bitmap_decompression_store == RDPConnection.conf.INTEGER_BITMAP_DECOMPRESSION) {
                    int[] pixeli = Bitmap.decompressInt(width, height, size, data, Bpp);
                    if (pixeli != null) {
                        wi.setRGB(left, top, cx, cy, pixeli, 0, width);
                        EventWakeUp.getInstance().imageSegmented(left, top, ARDP5.wi.getSubimage(left, top, cx, cy));
                    } else {
//                        logger.warn("Could not decompress bitmap");
                    }
                } else if (RDPConnection.conf.bitmap_decompression_store == RDPConnection.conf.BUFFEREDIMAGE_BITMAP_DECOMPRESSION) {
                    Image pix = Bitmap.decompressImg(width, height, size, data, Bpp, null);
                    if (pix != null) {
                        EventWakeUp.getInstance().image(pix);
                        EventWakeUp.getInstance().imageSegmented(0, 0, pix);
                    } else {
//                        logger.warn("Could not decompress bitmap");
                    }
                } else {
                    wi = Bitmap.decompressImgDirect(width, height, size, data, Bpp, null, left, top, wi);
                    EventWakeUp.getInstance().imageSegmented(0, 0, wi.getBufferedImage());
                }
            }
        }
        RDPConnection.sc.setImage(wi);
        EventWakeUp.getInstance().setImage(RDPConnection.sc);
    }

    protected void processPalette(RdpPackage data) {
        int n_colors;
        IndexColorModel cm;
        byte[] palette;

        byte[] red;
        byte[] green;
        byte[] blue;
        int j = 0;

        data.incrementPosition(2); // pad
        n_colors = data.getLittleEndian16(); // Number of Colors in Palette
        data.incrementPosition(2); // pad
        palette = new byte[n_colors * 3];
        red = new byte[n_colors];
        green = new byte[n_colors];
        blue = new byte[n_colors];
        data.copyToByteArray(palette, 0, data.getPosition(), palette.length);
        data.incrementPosition(palette.length);
        for (int i = 0; i < n_colors; i++) {
            red[i] = palette[j];
            green[i] = palette[j + 1];
            blue[i] = palette[j + 2];
            j += 3;
        }
        cm = new IndexColorModel(8, n_colors, red, green, blue);
        wi.setIndexColorModel(cm);
    }

    public void registerDrawingSurface() {
    }

    /* Process a null system pointer PDU */
    protected void process_null_system_pointer_pdu(RdpPackage s) throws RdesktopException {
        if (g_null_cursor == null) {
            byte[] null_pointer_mask = new byte[1], null_pointer_data = new byte[24];
            null_pointer_mask[0] = (byte) 0x80;
        }
        setSubCursor(g_null_cursor);
    }

    protected void process_colour_pointer_pdu(RdpPackage data) throws RdesktopException {
//        logger.debug("Rdp.RDP_POINTER_COLOR");
        int x, y, width, height, cache_idx, masklen, datalen;
        byte[] mask, pixel;
        Cursor cursor;

        cache_idx = data.getLittleEndian16();
        x = data.getLittleEndian16();
        y = data.getLittleEndian16();
        width = data.getLittleEndian16();
        height = data.getLittleEndian16();
        masklen = data.getLittleEndian16();
        datalen = data.getLittleEndian16();
        mask = new byte[masklen];
        pixel = new byte[datalen];
        data.copyToByteArray(pixel, 0, data.getPosition(), datalen);
        data.incrementPosition(datalen);
        data.copyToByteArray(mask, 0, data.getPosition(), masklen);
        data.incrementPosition(masklen);

        cursor = OrdersJPanel.mb.createCursor(x, y, width, height, mask, pixel, cache_idx);

        setSubCursor(cursor);
        cache.putCursor(cache_idx, cursor);
    }

    protected void process_cached_pointer_pdu(RdpPackage data) throws RdesktopException {
        int cache_idx = data.getLittleEndian16();
        setSubCursor(cache.getCursor(cache_idx));
    }

    private void setSubCursor(Cursor cursor) {
    }
}
TOP

Related Classes of com.lixia.rdp.rdp5.ARDP5

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.