231 lines
9.4 KiB
C
231 lines
9.4 KiB
C
/****************************************************************************/
|
|
// oe2.h
|
|
//
|
|
// Header for RDP field compression.
|
|
//
|
|
// Copyright (C) 1997-2000 Microsoft Corporation
|
|
/****************************************************************************/
|
|
#ifndef __OE2_H
|
|
#define __OE2_H
|
|
|
|
|
|
/****************************************************************************/
|
|
// Field compression (OE2) overview
|
|
//
|
|
// OE2 compression maintains a copy of each field value of the last order
|
|
// sent, plus other state information like the last bounding rectangle used
|
|
// and the last order type. OE2 encoding involves comparing a new display
|
|
// order to the last copy, and sending only the fields which have changed.
|
|
// Other specialized encoding occurs for certain fields declared to be of
|
|
// "coord" type, meaning that a one-byte delta can be sent instead of a
|
|
// 2-byte value, if the delta will fit into 8 bits.
|
|
//
|
|
// The wire format for OE2 encoded orders consists of the following fields:
|
|
//
|
|
// +------------+------+-------------+--------+----------------+
|
|
// | Ctrl flags | Type | Field flags | Bounds | Encoded Fields |
|
|
// +------------+------+-------------+--------+----------------+
|
|
//
|
|
// Control flags: Required byte, corresponding to a TS_ORDER_HEADER and
|
|
// available flags. Always contains at least TS_STANDARD flag. These
|
|
// flags describe the following encoding; flag meanings are discussed
|
|
// below.
|
|
//
|
|
// Type: If TS_TYPE_CHANGE is present in the control flags, this is a one-
|
|
// byte order type value. The initial value agreed-on by both server
|
|
// and client is TS_ENC_PATBLT_ORDER.
|
|
//
|
|
// Field flags: One or more bytes, where the number of bytes is ceil(((number
|
|
// of order fields) + 1) / 8). The "+ 1" in that equation is historical
|
|
// and means that the first byte of field flags can only encompass 7
|
|
// flag bits. The presence of these flags is also governed by the control
|
|
// flags TS_ZERO_FIELD_BYTE_BIT0 and TS_ZERO_FIELD_BYTE_BIT1
|
|
// (see at128.h description). The ordering of the bytes is as a DWORD
|
|
// -- the low order byte is first. The field flags indicate the presence
|
|
// of an order field in the encoded fields portion of the packet.
|
|
// The ordering of the flags proceeds from 0x01 corresponding to the
|
|
// first order field, 0x02 the second, 0x04 the third, etc.
|
|
//
|
|
// Bounds: The presence of this field is governed by the TS_BOUNDS control
|
|
// flag, which indicates the order must have a bounding region applied.
|
|
// If control flag TS_ZERO_BOUNDS_DELTAS is set, the bound rect to be
|
|
// used is the same as the last bound rect used. Otherwise, the
|
|
// bounds are encoded as an encoding description byte followed by one
|
|
// or more encoded bounds. The description byte contains two flags
|
|
// for each of the left, top, right, and bottom rect components.
|
|
// One flag (TS_BOUND_XXX) indicates that the component is present
|
|
// and encoded as a 2-byte Intel-ordering value. The other flag
|
|
// (TS_BOUND_DELTA_XXX) indicates the component is present and encoded
|
|
// as a one-byte value used as an offset (-128 to 127) from the previous
|
|
// value of the component. If neither flag is present the component
|
|
// value is the same as used last. The initial value for the bounds
|
|
// agreed-on by both server and client is the zero rect (0, 0, 0, 0).
|
|
//
|
|
// Encoded fields: These are the encoded order field values whose presence
|
|
// is governed by the field flags. The fields are encoded in order if
|
|
// present. The control flag TS_DELTA_COORDINATES is set if all COORD
|
|
// type fields in the order can be specified as a one-byte delta from
|
|
// their last values. If a field is not present its value is the same
|
|
// as the last value sent. The initial values the client and server
|
|
// use for all fields is zero. See the order field description tables in
|
|
// noe2disp.c for specific order information.
|
|
/****************************************************************************/
|
|
|
|
|
|
/****************************************************************************/
|
|
// Defines
|
|
/****************************************************************************/
|
|
#define MAX_BOUNDS_ENCODE_SIZE 9
|
|
#define MAX_REPLAY_CLIPPED_ORDER_SIZE (1 + MAX_BOUNDS_ENCODE_SIZE)
|
|
|
|
#define OE2_CONTROL_FLAGS_FIELD_SIZE 1
|
|
#define OE2_TYPE_FIELD_SIZE 1
|
|
#define OE2_MAX_FIELD_FLAG_BYTES 3
|
|
|
|
#define MAX_ENCODED_ORDER_PREFIX_BYTES (OE2_CONTROL_FLAGS_FIELD_SIZE + \
|
|
OE2_TYPE_FIELD_SIZE + OE2_MAX_FIELD_FLAG_BYTES + \
|
|
MAX_BOUNDS_ENCODE_SIZE)
|
|
|
|
// Max size: 1 control flag + 1 type change byte + num field flag bytes +
|
|
// 9 bounds bytes + fields.
|
|
#define MAX_ORDER_SIZE(_NumRects, _NumFieldFlagBytes, _MaxFieldSize) \
|
|
(2 + (_NumFieldFlagBytes) + ((_NumRects == 0) ? 0 : 9) + \
|
|
(_MaxFieldSize))
|
|
|
|
|
|
/****************************************************************************/
|
|
// Types
|
|
/****************************************************************************/
|
|
|
|
// INT_FMT_FIELD: Const data definitions for table-based OE2 order translation.
|
|
// Describes the source intermediate and destination wire data formats.
|
|
//
|
|
// FieldPos: Byte offset into the source intermediate format for the field.
|
|
// FieldUnencodedLen: Length of the source field.
|
|
// FieldEncodedLen: Length of the destination field (wore format).
|
|
// FieldSigned: Flag for signed field value.
|
|
// FieldType: Descriptor that specifies how to translate the field.
|
|
typedef struct
|
|
{
|
|
unsigned FieldPos;
|
|
unsigned FieldUnencodedLen;
|
|
unsigned FieldEncodedLen;
|
|
BOOL FieldSigned;
|
|
unsigned FieldType;
|
|
} INT_FMT_FIELD;
|
|
typedef INT_FMT_FIELD const *PINT_FMT_FIELD;
|
|
|
|
|
|
/****************************************************************************/
|
|
// Prototypes and inlines
|
|
/****************************************************************************/
|
|
void OE2_Reset(void);
|
|
void OE2_EncodeBounds(BYTE *, BYTE **, RECTL *);
|
|
unsigned OE2_CheckZeroFlagBytes(BYTE *, BYTE *, unsigned, unsigned);
|
|
void OE2_TableEncodeOrderFields(BYTE *, PUINT32_UA, BYTE **, PINT_FMT_FIELD,
|
|
unsigned, BYTE *, BYTE *);
|
|
unsigned OE2_EncodeOrder(BYTE *, unsigned, unsigned, BYTE *, BYTE *,
|
|
PINT_FMT_FIELD, RECTL *);
|
|
|
|
|
|
/****************************************************************************/
|
|
// OE2_EncodeOrderType
|
|
//
|
|
// Used by order encoding paths to encode the order type byte if different
|
|
// from the last order.
|
|
//
|
|
// void OE2_EncodeOrderType(
|
|
// BYTE *pControlFlags,
|
|
// BYTE **ppBuffer,
|
|
// unsigned OrderType);
|
|
/****************************************************************************/
|
|
#define OE2_EncodeOrderType(_pControlFlags, _ppBuffer, _OrderType) \
|
|
{ \
|
|
if (oe2LastOrderType != (_OrderType)) { \
|
|
*(_pControlFlags) |= TS_TYPE_CHANGE; \
|
|
**(_ppBuffer) = (BYTE)(_OrderType); \
|
|
(*(_ppBuffer))++; \
|
|
oe2LastOrderType = (_OrderType); \
|
|
} \
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// OE2_CheckOneZeroFlagByte
|
|
//
|
|
// 1-field-flag-byte version of OE2_CheckZeroFlagBytes(), optimizes out the
|
|
// generalized loop.
|
|
/****************************************************************************/
|
|
__inline unsigned OE2_CheckOneZeroFlagByte(
|
|
BYTE *pControlFlags,
|
|
BYTE *pFieldFlag,
|
|
unsigned PostFlagsDataLength)
|
|
{
|
|
if (*pFieldFlag != 0) {
|
|
return 0;
|
|
}
|
|
else {
|
|
*pControlFlags |= (1 << TS_ZERO_FIELD_COUNT_SHIFT);
|
|
memmove(pFieldFlag, pFieldFlag + 1, PostFlagsDataLength);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// OE2_CheckTwoZeroFlagBytes
|
|
//
|
|
// 2-field-flag-byte version of OE2_CheckZeroFlagBytes(), optimizes out the
|
|
// generalized loop.
|
|
/****************************************************************************/
|
|
__inline unsigned OE2_CheckTwoZeroFlagBytes(
|
|
BYTE *pControlFlags,
|
|
BYTE *pFieldFlags,
|
|
unsigned PostFlagsDataLength)
|
|
{
|
|
if (pFieldFlags[1] != 0) {
|
|
return 0;
|
|
}
|
|
else if (pFieldFlags[0] != 0) {
|
|
*pControlFlags |= (1 << TS_ZERO_FIELD_COUNT_SHIFT);
|
|
memmove(pFieldFlags + 1, pFieldFlags + 2, PostFlagsDataLength);
|
|
return 1;
|
|
}
|
|
else {
|
|
*pControlFlags |= (2 << TS_ZERO_FIELD_COUNT_SHIFT);
|
|
memmove(pFieldFlags, pFieldFlags + 2, PostFlagsDataLength);
|
|
return 2;
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
// OE2_EmitClippedReplayOrder
|
|
//
|
|
// Creates a "play-it-again" order -- same order type and all fields
|
|
// the same as previous, except with a different bound rect.
|
|
//
|
|
// void OE2_EmitClippedReplayOrder(
|
|
// BYTE **ppBuffer,
|
|
// unsigned NumFieldFlagBytes,
|
|
// RECTL *pClipRect)
|
|
/****************************************************************************/
|
|
#define OE2_EmitClippedReplayOrder(_ppBuffer, _NumFieldFlagBytes, _pClipRect) \
|
|
{ \
|
|
BYTE *pBuffer = *(_ppBuffer); \
|
|
\
|
|
/* Control flags are primary order plus all field flags bytes zero. */ \
|
|
*pBuffer++ = TS_STANDARD | TS_BOUNDS | \
|
|
((_NumFieldFlagBytes) << TS_ZERO_FIELD_COUNT_SHIFT); \
|
|
\
|
|
/* Construct the new bounds rect just after this. */ \
|
|
OE2_EncodeBounds(pBuffer - 1, &pBuffer, (_pClipRect)); \
|
|
\
|
|
*(_ppBuffer) = pBuffer; \
|
|
}
|
|
|
|
|
|
|
|
#endif // __OE2_H
|
|
|