/* 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) {
}
}