2022-04-29 14:13:58 -04:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2014-2015 Sylvain Peyrefitte
|
|
|
|
|
*
|
|
|
|
|
* This file is part of node-rdpjs.
|
|
|
|
|
*
|
|
|
|
|
* node-rdpjs is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
var caps = require('./caps');
|
|
|
|
|
var type = require('../../core').type;
|
|
|
|
|
var log = require('../../core').log;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240576.aspx
|
|
|
|
|
*/
|
|
|
|
|
var PDUType = {
|
|
|
|
|
PDUTYPE_DEMANDACTIVEPDU : 0x11,
|
|
|
|
|
PDUTYPE_CONFIRMACTIVEPDU : 0x13,
|
|
|
|
|
PDUTYPE_DEACTIVATEALLPDU : 0x16,
|
|
|
|
|
PDUTYPE_DATAPDU : 0x17,
|
|
|
|
|
PDUTYPE_SERVER_REDIR_PKT : 0x1A
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
|
|
|
|
*/
|
|
|
|
|
var PDUType2 = {
|
|
|
|
|
PDUTYPE2_UPDATE : 0x02,
|
|
|
|
|
PDUTYPE2_CONTROL : 0x14,
|
|
|
|
|
PDUTYPE2_POINTER : 0x1B,
|
|
|
|
|
PDUTYPE2_INPUT : 0x1C,
|
|
|
|
|
PDUTYPE2_SYNCHRONIZE : 0x1F,
|
|
|
|
|
PDUTYPE2_REFRESH_RECT : 0x21,
|
|
|
|
|
PDUTYPE2_PLAY_SOUND : 0x22,
|
|
|
|
|
PDUTYPE2_SUPPRESS_OUTPUT : 0x23,
|
|
|
|
|
PDUTYPE2_SHUTDOWN_REQUEST : 0x24,
|
|
|
|
|
PDUTYPE2_SHUTDOWN_DENIED : 0x25,
|
|
|
|
|
PDUTYPE2_SAVE_SESSION_INFO : 0x26,
|
|
|
|
|
PDUTYPE2_FONTLIST : 0x27,
|
|
|
|
|
PDUTYPE2_FONTMAP : 0x28,
|
|
|
|
|
PDUTYPE2_SET_KEYBOARD_INDICATORS : 0x29,
|
|
|
|
|
PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST : 0x2B,
|
|
|
|
|
PDUTYPE2_BITMAPCACHE_ERROR_PDU : 0x2C,
|
|
|
|
|
PDUTYPE2_SET_KEYBOARD_IME_STATUS : 0x2D,
|
|
|
|
|
PDUTYPE2_OFFSCRCACHE_ERROR_PDU : 0x2E,
|
|
|
|
|
PDUTYPE2_SET_ERROR_INFO_PDU : 0x2F,
|
|
|
|
|
PDUTYPE2_DRAWNINEGRID_ERROR_PDU : 0x30,
|
|
|
|
|
PDUTYPE2_DRAWGDIPLUS_ERROR_PDU : 0x31,
|
|
|
|
|
PDUTYPE2_ARC_STATUS_PDU : 0x32,
|
|
|
|
|
PDUTYPE2_STATUS_INFO_PDU : 0x36,
|
|
|
|
|
PDUTYPE2_MONITOR_LAYOUT_PDU : 0x37
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
|
|
|
|
*/
|
|
|
|
|
var StreamId = {
|
|
|
|
|
STREAM_UNDEFINED : 0x00,
|
|
|
|
|
STREAM_LOW : 0x01,
|
|
|
|
|
STREAM_MED : 0x02,
|
|
|
|
|
STREAM_HI : 0x04
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
|
|
|
|
*/
|
|
|
|
|
var CompressionOrder = {
|
|
|
|
|
CompressionTypeMask : 0x0F,
|
|
|
|
|
PACKET_COMPRESSED : 0x20,
|
|
|
|
|
PACKET_AT_FRONT : 0x40,
|
|
|
|
|
PACKET_FLUSHED : 0x80
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
|
|
|
|
*/
|
|
|
|
|
var CompressionType = {
|
|
|
|
|
PACKET_COMPR_TYPE_8K : 0x0,
|
|
|
|
|
PACKET_COMPR_TYPE_64K : 0x1,
|
|
|
|
|
PACKET_COMPR_TYPE_RDP6 : 0x2,
|
|
|
|
|
PACKET_COMPR_TYPE_RDP61 : 0x3,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240492.aspx
|
|
|
|
|
*/
|
|
|
|
|
var Action = {
|
|
|
|
|
CTRLACTION_REQUEST_CONTROL : 0x0001,
|
|
|
|
|
CTRLACTION_GRANTED_CONTROL : 0x0002,
|
|
|
|
|
CTRLACTION_DETACH : 0x0003,
|
|
|
|
|
CTRLACTION_COOPERATE : 0x0004
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240495.aspx
|
|
|
|
|
*/
|
|
|
|
|
var PersistentKeyListFlag = {
|
|
|
|
|
PERSIST_FIRST_PDU : 0x01,
|
|
|
|
|
PERSIST_LAST_PDU : 0x02
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240612.aspx
|
|
|
|
|
*/
|
|
|
|
|
var BitmapFlag = {
|
|
|
|
|
BITMAP_COMPRESSION : 0x0001,
|
|
|
|
|
NO_BITMAP_COMPRESSION_HDR : 0x0400
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240608.aspx
|
|
|
|
|
*/
|
|
|
|
|
var UpdateType = {
|
|
|
|
|
UPDATETYPE_ORDERS : 0x0000,
|
|
|
|
|
UPDATETYPE_BITMAP : 0x0001,
|
|
|
|
|
UPDATETYPE_PALETTE : 0x0002,
|
|
|
|
|
UPDATETYPE_SYNCHRONIZE : 0x0003
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240608.aspx
|
|
|
|
|
*/
|
|
|
|
|
var UpdateType = {
|
|
|
|
|
UPDATETYPE_ORDERS : 0x0000,
|
|
|
|
|
UPDATETYPE_BITMAP : 0x0001,
|
|
|
|
|
UPDATETYPE_PALETTE : 0x0002,
|
|
|
|
|
UPDATETYPE_SYNCHRONIZE : 0x0003
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240583.aspx
|
|
|
|
|
*/
|
|
|
|
|
var InputMessageType = {
|
|
|
|
|
INPUT_EVENT_SYNC : 0x0000,
|
|
|
|
|
INPUT_EVENT_UNUSED : 0x0002,
|
|
|
|
|
INPUT_EVENT_SCANCODE : 0x0004,
|
|
|
|
|
INPUT_EVENT_UNICODE : 0x0005,
|
|
|
|
|
INPUT_EVENT_MOUSE : 0x8001,
|
|
|
|
|
INPUT_EVENT_MOUSEX : 0x8002
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240586.aspx
|
|
|
|
|
*/
|
|
|
|
|
var PointerFlag = {
|
|
|
|
|
PTRFLAGS_HWHEEL : 0x0400,
|
|
|
|
|
PTRFLAGS_WHEEL : 0x0200,
|
|
|
|
|
PTRFLAGS_WHEEL_NEGATIVE : 0x0100,
|
|
|
|
|
WheelRotationMask : 0x01FF,
|
|
|
|
|
PTRFLAGS_MOVE : 0x0800,
|
|
|
|
|
PTRFLAGS_DOWN : 0x8000,
|
|
|
|
|
PTRFLAGS_BUTTON1 : 0x1000,
|
|
|
|
|
PTRFLAGS_BUTTON2 : 0x2000,
|
|
|
|
|
PTRFLAGS_BUTTON3 : 0x4000
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240584.aspx
|
|
|
|
|
*/
|
|
|
|
|
var KeyboardFlag = {
|
|
|
|
|
KBDFLAGS_EXTENDED : 0x0100,
|
|
|
|
|
KBDFLAGS_DOWN : 0x4000,
|
|
|
|
|
KBDFLAGS_RELEASE : 0x8000
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240622.aspx
|
|
|
|
|
*/
|
|
|
|
|
var FastPathUpdateType = {
|
|
|
|
|
FASTPATH_UPDATETYPE_ORDERS : 0x0,
|
|
|
|
|
FASTPATH_UPDATETYPE_BITMAP : 0x1,
|
|
|
|
|
FASTPATH_UPDATETYPE_PALETTE : 0x2,
|
|
|
|
|
FASTPATH_UPDATETYPE_SYNCHRONIZE : 0x3,
|
|
|
|
|
FASTPATH_UPDATETYPE_SURFCMDS : 0x4,
|
|
|
|
|
FASTPATH_UPDATETYPE_PTR_NULL : 0x5,
|
|
|
|
|
FASTPATH_UPDATETYPE_PTR_DEFAULT : 0x6,
|
|
|
|
|
FASTPATH_UPDATETYPE_PTR_POSITION : 0x8,
|
|
|
|
|
FASTPATH_UPDATETYPE_COLOR : 0x9,
|
|
|
|
|
FASTPATH_UPDATETYPE_CACHED : 0xA,
|
|
|
|
|
FASTPATH_UPDATETYPE_POINTER : 0xB
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240622.aspx
|
|
|
|
|
*/
|
|
|
|
|
var FastPathOutputCompression = {
|
|
|
|
|
FASTPATH_OUTPUT_COMPRESSION_USED : 0x2
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240648.aspx
|
|
|
|
|
*/
|
|
|
|
|
var Display = {
|
|
|
|
|
SUPPRESS_DISPLAY_UPDATES : 0x00,
|
|
|
|
|
ALLOW_DISPLAY_UPDATES : 0x01
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see https://msdn.microsoft.com/en-us/library/cc240588.aspx
|
|
|
|
|
*/
|
|
|
|
|
var ToogleFlag = {
|
|
|
|
|
TS_SYNC_SCROLL_LOCK : 0x00000001,
|
|
|
|
|
TS_SYNC_NUM_LOCK : 0x00000002,
|
|
|
|
|
TS_SYNC_CAPS_LOCK : 0x00000004,
|
|
|
|
|
TS_SYNC_KANA_LOCK : 0x00000008
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240544.aspx
|
|
|
|
|
*/
|
|
|
|
|
var ErrorInfo = {
|
|
|
|
|
ERRINFO_RPC_INITIATED_DISCONNECT : 0x00000001,
|
|
|
|
|
ERRINFO_RPC_INITIATED_LOGOFF : 0x00000002,
|
|
|
|
|
ERRINFO_IDLE_TIMEOUT : 0x00000003,
|
|
|
|
|
ERRINFO_LOGON_TIMEOUT : 0x00000004,
|
|
|
|
|
ERRINFO_DISCONNECTED_BY_OTHERCONNECTION : 0x00000005,
|
|
|
|
|
ERRINFO_OUT_OF_MEMORY : 0x00000006,
|
|
|
|
|
ERRINFO_SERVER_DENIED_CONNECTION : 0x00000007,
|
|
|
|
|
ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES : 0x00000009,
|
|
|
|
|
ERRINFO_SERVER_FRESH_CREDENTIALS_REQUIRED : 0x0000000A,
|
|
|
|
|
ERRINFO_RPC_INITIATED_DISCONNECT_BYUSER : 0x0000000B,
|
|
|
|
|
ERRINFO_LOGOFF_BY_USER : 0x0000000C,
|
|
|
|
|
ERRINFO_LICENSE_INTERNAL : 0x00000100,
|
|
|
|
|
ERRINFO_LICENSE_NO_LICENSE_SERVER : 0x00000101,
|
|
|
|
|
ERRINFO_LICENSE_NO_LICENSE : 0x00000102,
|
|
|
|
|
ERRINFO_LICENSE_BAD_CLIENT_MSG : 0x00000103,
|
|
|
|
|
ERRINFO_LICENSE_HWID_DOESNT_MATCH_LICENSE : 0x00000104,
|
|
|
|
|
ERRINFO_LICENSE_BAD_CLIENT_LICENSE : 0x00000105,
|
|
|
|
|
ERRINFO_LICENSE_CANT_FINISH_PROTOCOL : 0x00000106,
|
|
|
|
|
ERRINFO_LICENSE_CLIENT_ENDED_PROTOCOL : 0x00000107,
|
|
|
|
|
ERRINFO_LICENSE_BAD_CLIENT_ENCRYPTION : 0x00000108,
|
|
|
|
|
ERRINFO_LICENSE_CANT_UPGRADE_LICENSE : 0x00000109,
|
|
|
|
|
ERRINFO_LICENSE_NO_REMOTE_CONNECTIONS : 0x0000010A,
|
|
|
|
|
ERRINFO_CB_DESTINATION_NOT_FOUND : 0x0000400,
|
|
|
|
|
ERRINFO_CB_LOADING_DESTINATION : 0x0000402,
|
|
|
|
|
ERRINFO_CB_REDIRECTING_TO_DESTINATION : 0x0000404,
|
|
|
|
|
ERRINFO_CB_SESSION_ONLINE_VM_WAKE : 0x0000405,
|
|
|
|
|
ERRINFO_CB_SESSION_ONLINE_VM_BOOT : 0x0000406,
|
|
|
|
|
ERRINFO_CB_SESSION_ONLINE_VM_NO_DNS : 0x0000407,
|
|
|
|
|
ERRINFO_CB_DESTINATION_POOL_NOT_FREE : 0x0000408,
|
|
|
|
|
ERRINFO_CB_CONNECTION_CANCELLED : 0x0000409,
|
|
|
|
|
ERRINFO_CB_CONNECTION_ERROR_INVALID_SETTINGS : 0x0000410,
|
|
|
|
|
ERRINFO_CB_SESSION_ONLINE_VM_BOOT_TIMEOUT : 0x0000411,
|
|
|
|
|
ERRINFO_CB_SESSION_ONLINE_VM_SESSMON_FAILED : 0x0000412,
|
|
|
|
|
ERRINFO_UNKNOWNPDUTYPE2 : 0x000010C9,
|
|
|
|
|
ERRINFO_UNKNOWNPDUTYPE : 0x000010CA,
|
|
|
|
|
ERRINFO_DATAPDUSEQUENCE : 0x000010CB,
|
|
|
|
|
ERRINFO_CONTROLPDUSEQUENCE : 0x000010CD,
|
|
|
|
|
ERRINFO_INVALIDCONTROLPDUACTION : 0x000010CE,
|
|
|
|
|
ERRINFO_INVALIDINPUTPDUTYPE : 0x000010CF,
|
|
|
|
|
ERRINFO_INVALIDINPUTPDUMOUSE : 0x000010D0,
|
|
|
|
|
ERRINFO_INVALIDREFRESHRECTPDU : 0x000010D1,
|
|
|
|
|
ERRINFO_CREATEUSERDATAFAILED : 0x000010D2,
|
|
|
|
|
ERRINFO_CONNECTFAILED : 0x000010D3,
|
|
|
|
|
ERRINFO_CONFIRMACTIVEWRONGSHAREID : 0x000010D4,
|
|
|
|
|
ERRINFO_CONFIRMACTIVEWRONGORIGINATOR : 0x000010D5,
|
|
|
|
|
ERRINFO_PERSISTENTKEYPDUBADLENGTH : 0x000010DA,
|
|
|
|
|
ERRINFO_PERSISTENTKEYPDUILLEGALFIRST : 0x000010DB,
|
|
|
|
|
ERRINFO_PERSISTENTKEYPDUTOOMANYTOTALKEYS : 0x000010DC,
|
|
|
|
|
ERRINFO_PERSISTENTKEYPDUTOOMANYCACHEKEYS : 0x000010DD,
|
|
|
|
|
ERRINFO_INPUTPDUBADLENGTH : 0x000010DE,
|
|
|
|
|
ERRINFO_BITMAPCACHEERRORPDUBADLENGTH : 0x000010DF,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT : 0x000010E0,
|
|
|
|
|
ERRINFO_VCHANNELDATATOOSHORT : 0x000010E1,
|
|
|
|
|
ERRINFO_SHAREDATATOOSHORT : 0x000010E2,
|
|
|
|
|
ERRINFO_BADSUPRESSOUTPUTPDU : 0x000010E3,
|
|
|
|
|
ERRINFO_CONFIRMACTIVEPDUTOOSHORT : 0x000010E5,
|
|
|
|
|
ERRINFO_CAPABILITYSETTOOSMALL : 0x000010E7,
|
|
|
|
|
ERRINFO_CAPABILITYSETTOOLARGE : 0x000010E8,
|
|
|
|
|
ERRINFO_NOCURSORCACHE : 0x000010E9,
|
|
|
|
|
ERRINFO_BADCAPABILITIES : 0x000010EA,
|
|
|
|
|
ERRINFO_VIRTUALCHANNELDECOMPRESSIONERR : 0x000010EC,
|
|
|
|
|
ERRINFO_INVALIDVCCOMPRESSIONTYPE : 0x000010ED,
|
|
|
|
|
ERRINFO_INVALIDCHANNELID : 0x000010EF,
|
|
|
|
|
ERRINFO_VCHANNELSTOOMANY : 0x000010F0,
|
|
|
|
|
ERRINFO_REMOTEAPPSNOTENABLED : 0x000010F3,
|
|
|
|
|
ERRINFO_CACHECAPNOTSET : 0x000010F4,
|
|
|
|
|
ERRINFO_BITMAPCACHEERRORPDUBADLENGTH2 : 0x000010F5,
|
|
|
|
|
ERRINFO_OFFSCRCACHEERRORPDUBADLENGTH : 0x000010F6,
|
|
|
|
|
ERRINFO_DNGCACHEERRORPDUBADLENGTH : 0x000010F7,
|
|
|
|
|
ERRINFO_GDIPLUSPDUBADLENGTH : 0x000010F8,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT2 : 0x00001111,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT3 : 0x00001112,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT4 : 0x00001113,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT5 : 0x00001114,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT6 : 0x00001115,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT7 : 0x00001116,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT8 : 0x00001117,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT9 : 0x00001118,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT10 : 0x00001119,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT11 : 0x0000111A,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT12 : 0x0000111B,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT13 : 0x0000111C,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT14 : 0x0000111D,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT15 : 0x0000111E,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT16 : 0x0000111F,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT17 : 0x00001120,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT18 : 0x00001121,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT19 : 0x00001122,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT20 : 0x00001123,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT21 : 0x00001124,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT22 : 0x00001125,
|
|
|
|
|
ERRINFO_SECURITYDATATOOSHORT23 : 0x00001126,
|
|
|
|
|
ERRINFO_BADMONITORDATA : 0x00001129,
|
|
|
|
|
ERRINFO_VCDECOMPRESSEDREASSEMBLEFAILED : 0x0000112A,
|
|
|
|
|
ERRINFO_VCDATATOOLONG : 0x0000112B,
|
|
|
|
|
ERRINFO_BAD_FRAME_ACK_DATA : 0x0000112C,
|
|
|
|
|
ERRINFO_GRAPHICSMODENOTSUPPORTED : 0x0000112D,
|
|
|
|
|
ERRINFO_GRAPHICSSUBSYSTEMRESETFAILED : 0x0000112E,
|
|
|
|
|
ERRINFO_GRAPHICSSUBSYSTEMFAILED : 0x0000112F,
|
|
|
|
|
ERRINFO_TIMEZONEKEYNAMELENGTHTOOSHORT : 0x00001130,
|
|
|
|
|
ERRINFO_TIMEZONEKEYNAMELENGTHTOOLONG : 0x00001131,
|
|
|
|
|
ERRINFO_DYNAMICDSTDISABLEDFIELDMISSING : 0x00001132,
|
|
|
|
|
ERRINFO_VCDECODINGERROR : 0x00001133,
|
|
|
|
|
ERRINFO_UPDATESESSIONKEYFAILED : 0x00001191,
|
|
|
|
|
ERRINFO_DECRYPTFAILED : 0x00001192,
|
|
|
|
|
ERRINFO_ENCRYPTFAILED : 0x00001193,
|
|
|
|
|
ERRINFO_ENCPKGMISMATCH : 0x00001194,
|
|
|
|
|
ERRINFO_DECRYPTFAILED2 : 0x00001195
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240576.aspx
|
|
|
|
|
* @param length {integer} length of entire pdu packet
|
|
|
|
|
* @param pduType {PDUType.*} type of pdu packet
|
|
|
|
|
* @param userId {integer}
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function shareControlHeader(length, pduType, userId, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
totalLength : new type.UInt16Le(length),
|
|
|
|
|
pduType : new type.UInt16Le(pduType),
|
|
|
|
|
// for xp sp3 and deactiveallpdu PDUSource may not be present
|
|
|
|
|
PDUSource : new type.UInt16Le(userId, { optional : true })
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240577.aspx
|
|
|
|
|
* @param length {integer} lezngth of entire packet
|
|
|
|
|
* @param pduType2 {PDUType2.*} sub PDU type
|
|
|
|
|
* @param shareId {integer} global layer id
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function shareDataHeader(length, pduType2, shareId, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
shareId : new type.UInt32Le(shareId),
|
|
|
|
|
pad1 : new type.UInt8(),
|
|
|
|
|
streamId : new type.UInt8(StreamId.STREAM_LOW),
|
|
|
|
|
uncompressedLength : new type.UInt16Le(function() {
|
|
|
|
|
return length.value - 8;
|
|
|
|
|
}),
|
|
|
|
|
pduType2 : new type.UInt8(pduType2),
|
|
|
|
|
compressedType : new type.UInt8(),
|
|
|
|
|
compressedLength : new type.UInt16Le()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240485.aspx
|
|
|
|
|
* @param capabilities {type.Component} capabilities array
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function demandActivePDU(capabilities, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE__ : PDUType.PDUTYPE_DEMANDACTIVEPDU,
|
|
|
|
|
shareId : new type.UInt32Le(),
|
|
|
|
|
lengthSourceDescriptor : new type.UInt16Le(function() {
|
|
|
|
|
return self.sourceDescriptor.size();
|
|
|
|
|
}),
|
|
|
|
|
lengthCombinedCapabilities : new type.UInt16Le(function() {
|
|
|
|
|
return self.numberCapabilities.size() + self.pad2Octets.size() + self.capabilitySets.size();
|
|
|
|
|
}),
|
|
|
|
|
sourceDescriptor : new type.BinaryString(Buffer.from('node-rdpjs', 'binary'), { readLength : new type.CallableValue(function() {
|
|
|
|
|
return self.lengthSourceDescriptor.value
|
|
|
|
|
}) }),
|
|
|
|
|
numberCapabilities : new type.UInt16Le(function() {
|
|
|
|
|
return self.capabilitySets.obj.length;
|
|
|
|
|
}),
|
|
|
|
|
pad2Octets : new type.UInt16Le(),
|
|
|
|
|
capabilitySets : capabilities || new type.Factory(function(s) {
|
|
|
|
|
self.capabilitySets = new type.Component([]);
|
|
|
|
|
for(var i = 0; i < self.numberCapabilities.value; i++) {
|
|
|
|
|
self.capabilitySets.obj.push(caps.capability().read(s))
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
sessionId : new type.UInt32Le()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240488.aspx
|
|
|
|
|
* @param capabilities {type.Component} capabilities array
|
|
|
|
|
* @param shareId {integer} session id
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function confirmActivePDU(capabilities, shareId, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE__ : PDUType.PDUTYPE_CONFIRMACTIVEPDU,
|
|
|
|
|
shareId : new type.UInt32Le(shareId),
|
|
|
|
|
originatorId : new type.UInt16Le(0x03EA, { constant : true }),
|
|
|
|
|
lengthSourceDescriptor : new type.UInt16Le(function() {
|
|
|
|
|
return self.sourceDescriptor.size();
|
|
|
|
|
}),
|
|
|
|
|
lengthCombinedCapabilities : new type.UInt16Le(function() {
|
|
|
|
|
return self.numberCapabilities.size() + self.pad2Octets.size() + self.capabilitySets.size();
|
|
|
|
|
}),
|
|
|
|
|
sourceDescriptor : new type.BinaryString(Buffer.from('rdpy', 'binary'), { readLength : new type.CallableValue(function() {
|
|
|
|
|
return self.lengthSourceDescriptor.value
|
|
|
|
|
}) }),
|
|
|
|
|
numberCapabilities : new type.UInt16Le(function() {
|
|
|
|
|
return self.capabilitySets.obj.length;
|
|
|
|
|
}),
|
|
|
|
|
pad2Octets : new type.UInt16Le(),
|
|
|
|
|
capabilitySets : capabilities || new type.Factory(function(s) {
|
|
|
|
|
self.capabilitySets = new type.Component([]);
|
|
|
|
|
for(var i = 0; i < self.numberCapabilities.value; i++) {
|
|
|
|
|
self.capabilitySets.obj.push(caps.capability().read(s))
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240536.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function deactiveAllPDU(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE__ : PDUType.PDUTYPE_DEACTIVATEALLPDU,
|
|
|
|
|
shareId : new type.UInt32Le(),
|
|
|
|
|
lengthSourceDescriptor : new type.UInt16Le(function() {
|
|
|
|
|
return self.sourceDescriptor.size();
|
|
|
|
|
}),
|
|
|
|
|
sourceDescriptor : new type.BinaryString(Buffer.from('rdpy', 'binary'), { readLength : new type.CallableValue(function() {
|
|
|
|
|
self.lengthSourceDescriptor
|
|
|
|
|
}) })
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240490.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function synchronizeDataPDU(targetUser, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2__ : PDUType2.PDUTYPE2_SYNCHRONIZE,
|
|
|
|
|
messageType : new type.UInt16Le(1, { constant : true }),
|
|
|
|
|
targetUser : new type.UInt16Le(targetUser)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240492.aspx
|
|
|
|
|
* @param action {integer}
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function controlDataPDU(action, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2__ : PDUType2.PDUTYPE2_CONTROL,
|
|
|
|
|
action : new type.UInt16Le(action),
|
|
|
|
|
grantId : new type.UInt16Le(),
|
|
|
|
|
controlId : new type.UInt32Le()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240544.aspx
|
|
|
|
|
* @param errorInfo {integer}
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function errorInfoDataPDU(errorInfo, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2__ : PDUType2.PDUTYPE2_SET_ERROR_INFO_PDU,
|
|
|
|
|
errorInfo : new type.UInt32Le(errorInfo)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240498.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function fontListDataPDU(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2__ : PDUType2.PDUTYPE2_FONTLIST,
|
|
|
|
|
numberFonts : new type.UInt16Le(),
|
|
|
|
|
totalNumFonts : new type.UInt16Le(),
|
|
|
|
|
listFlags : new type.UInt16Le(0x0003),
|
|
|
|
|
entrySize : new type.UInt16Le(0x0032)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240498.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function fontMapDataPDU(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2__ : PDUType2.PDUTYPE2_FONTMAP,
|
|
|
|
|
numberEntries : new type.UInt16Le(),
|
|
|
|
|
totalNumEntries : new type.UInt16Le(),
|
|
|
|
|
mapFlags : new type.UInt16Le(0x0003),
|
|
|
|
|
entrySize : new type.UInt16Le(0x0004)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240496.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function persistentListEntry(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
key1 : new type.UInt32Le(),
|
|
|
|
|
key2 : new type.UInt32Le()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240495.aspx
|
|
|
|
|
* @param entries {type.Component}
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function persistentListPDU(entries, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2__ : PDUType2.PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST,
|
|
|
|
|
numEntriesCache0 : new type.UInt16Le(),
|
|
|
|
|
numEntriesCache1 : new type.UInt16Le(),
|
|
|
|
|
numEntriesCache2 : new type.UInt16Le(),
|
|
|
|
|
numEntriesCache3 : new type.UInt16Le(),
|
|
|
|
|
numEntriesCache4 : new type.UInt16Le(),
|
|
|
|
|
totalEntriesCache0 : new type.UInt16Le(),
|
|
|
|
|
totalEntriesCache1 : new type.UInt16Le(),
|
|
|
|
|
totalEntriesCache2 : new type.UInt16Le(),
|
|
|
|
|
totalEntriesCache3 : new type.UInt16Le(),
|
|
|
|
|
totalEntriesCache4 : new type.UInt16Le(),
|
|
|
|
|
bitMask : new type.UInt8(),
|
|
|
|
|
pad2 : new type.UInt8(),
|
|
|
|
|
pad3 : new type.UInt16Le(),
|
|
|
|
|
entries : entries || new type.Factory(function(s) {
|
|
|
|
|
var numEntries = self.numEntriesCache0.value + self.numEntriesCache1.value + self.numEntriesCache2.value + self.numEntriesCache3.value + self.numEntriesCache4.value;
|
|
|
|
|
self.entries = new type.Component([]);
|
|
|
|
|
for(var i = 0; i < numEntries; i++) {
|
|
|
|
|
self.entries.obj.push(persistentListEntry().read(s));
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see https://msdn.microsoft.com/en-us/library/cc240588.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function synchronizeEvent(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__INPUT_MESSAGE_TYPE__ : InputMessageType.INPUT_EVENT_SYNC,
|
|
|
|
|
pad2Octets : new type.UInt16Le(),
|
|
|
|
|
toggleFlags : new type.UInt32Le()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240586.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function pointerEvent(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__INPUT_MESSAGE_TYPE__ : InputMessageType.INPUT_EVENT_MOUSE,
|
|
|
|
|
pointerFlags : new type.UInt16Le(),
|
|
|
|
|
xPos : new type.UInt16Le(),
|
|
|
|
|
yPos : new type.UInt16Le()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240584.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function scancodeKeyEvent(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__INPUT_MESSAGE_TYPE__ : InputMessageType.INPUT_EVENT_SCANCODE,
|
|
|
|
|
keyboardFlags : new type.UInt16Le(),
|
|
|
|
|
keyCode : new type.UInt16Le(),
|
|
|
|
|
pad2Octets : new type.UInt16Le()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240585.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function unicodeKeyEvent(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__INPUT_MESSAGE_TYPE__ : InputMessageType.INPUT_EVENT_UNICODE,
|
|
|
|
|
keyboardFlags : new type.UInt16Le(),
|
|
|
|
|
unicode : new type.UInt16Le(),
|
|
|
|
|
pad2Octets : new type.UInt16Le()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240583.aspx
|
|
|
|
|
* @param slowPathInputData {type.Component} message generate for slow path input event
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function slowPathInputEvent(slowPathInputData, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
eventTime : new type.UInt32Le(),
|
|
|
|
|
messageType : new type.UInt16Le(function() {
|
|
|
|
|
return self.slowPathInputData.obj.__INPUT_MESSAGE_TYPE__;
|
|
|
|
|
}),
|
|
|
|
|
slowPathInputData : slowPathInputData || new type.Factory(function(s) {
|
|
|
|
|
switch(self.messageType.value) {
|
|
|
|
|
case InputMessageType.INPUT_EVENT_SYNC:
|
|
|
|
|
self.slowPathInputData = synchronizeEvent().read(s);
|
|
|
|
|
break;
|
|
|
|
|
case InputMessageType.INPUT_EVENT_MOUSE:
|
|
|
|
|
self.slowPathInputData = pointerEvent().read(s);
|
|
|
|
|
break;
|
|
|
|
|
case InputMessageType.INPUT_EVENT_SCANCODE:
|
|
|
|
|
self.slowPathInputData = scancodeKeyEvent().read(s);
|
|
|
|
|
break;
|
|
|
|
|
case InputMessageType.INPUT_EVENT_UNICODE:
|
|
|
|
|
self.slowPathInputData = unicodeKeyEvent().read(s);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
log.error('unknown slowPathInputEvent ' + self.messageType.value);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc746160.aspx
|
|
|
|
|
* @param inputs {type.Component} list of inputs
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function clientInputEventPDU(inputs, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2__ : PDUType2.PDUTYPE2_INPUT,
|
|
|
|
|
numEvents : new type.UInt16Le(function() {
|
|
|
|
|
return self.slowPathInputEvents.obj.length;
|
|
|
|
|
}),
|
|
|
|
|
pad2Octets : new type.UInt16Le(),
|
|
|
|
|
slowPathInputEvents : inputs || new type.Factory(function(s) {
|
|
|
|
|
self.slowPathInputEvents = new type.Component([]);
|
|
|
|
|
for(var i = 0; i < self.numEvents.value; i++) {
|
|
|
|
|
self.slowPathInputEvents.obj.push(slowPathInputEvent().read(s));
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function shutdownRequestPDU(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2__ : PDUType2.PDUTYPE2_SHUTDOWN_REQUEST
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function shutdownDeniedPDU(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2__ : PDUType2.PDUTYPE2_SHUTDOWN_DENIED
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240643.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function inclusiveRectangle(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
left : new type.UInt16Le(),
|
|
|
|
|
top : new type.UInt16Le(),
|
|
|
|
|
right : new type.UInt16Le(),
|
|
|
|
|
bottom : new type.UInt16Le()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240648.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function supressOutputDataPDU(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2__ : PDUType2.PDUTYPE2_SUPPRESS_OUTPUT,
|
|
|
|
|
allowDisplayUpdates : new type.UInt8(),
|
|
|
|
|
pad3Octets : new type.Component([new type.UInt8(), new type.UInt8(), new type.UInt8()]),
|
|
|
|
|
desktopRect : inclusiveRectangle({ conditional : function() {
|
|
|
|
|
return self.allowDisplayUpdates.value === Display.ALLOW_DISPLAY_UPDATES;
|
|
|
|
|
} })
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240646.aspx
|
|
|
|
|
* @param rectangles {type.Component} list of inclusive rectangles
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function refreshRectPDU(rectangles, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2__ : PDUType2.PDUTYPE2_REFRESH_RECT,
|
|
|
|
|
numberOfAreas : UInt8(function() {
|
|
|
|
|
return self.areasToRefresh.obj.length;
|
|
|
|
|
}),
|
|
|
|
|
pad3Octets : new type.Component([new type.UInt8(), new type.UInt8(), new type.UInt8()]),
|
|
|
|
|
areasToRefresh : rectangles || new type.Factory(function(s) {
|
|
|
|
|
self.areasToRefresh = new type.Component([]);
|
|
|
|
|
for(var i = 0; i < self.numberOfAreas.value; i++) {
|
|
|
|
|
self.areasToRefresh.obj.push(inclusiveRectangle().read(s));
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240644.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function bitmapCompressedDataHeader(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
cbCompFirstRowSize : new type.UInt16Le(0x0000, { constant : true }),
|
|
|
|
|
// compressed data size
|
|
|
|
|
cbCompMainBodySize : new type.UInt16Le(),
|
|
|
|
|
cbScanWidth : new type.UInt16Le(),
|
|
|
|
|
// uncompressed data size
|
|
|
|
|
cbUncompressedSize : new type.UInt16Le()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see
|
|
|
|
|
* @param coord {object}
|
|
|
|
|
* .destLeft {integer}
|
|
|
|
|
* .destTop {integer}
|
|
|
|
|
* .destRight {integer}
|
|
|
|
|
* .destBottom {integer}
|
|
|
|
|
* .width {integer}
|
|
|
|
|
* .height {integer}
|
|
|
|
|
* .bitsPerPixel {integer}
|
|
|
|
|
* .data {Buffer}
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function bitmapData(coord, opt) {
|
|
|
|
|
coord = coord || {};
|
|
|
|
|
var self = {
|
|
|
|
|
destLeft : new type.UInt16Le(coord.destLeft),
|
|
|
|
|
destTop : new type.UInt16Le(coord.destTop),
|
|
|
|
|
destRight : new type.UInt16Le(coord.destRight),
|
|
|
|
|
destBottom : new type.UInt16Le(coord.destBottom),
|
|
|
|
|
width : new type.UInt16Le(coord.width),
|
|
|
|
|
height : new type.UInt16Le(coord.height),
|
|
|
|
|
bitsPerPixel : new type.UInt16Le(coord.bitsPerPixel),
|
|
|
|
|
flags : new type.UInt16Le(),
|
|
|
|
|
bitmapLength : new type.UInt16Le(function() {
|
|
|
|
|
return self.bitmapComprHdr.size() + self.bitmapDataStream.size();
|
|
|
|
|
}),
|
|
|
|
|
bitmapComprHdr : bitmapCompressedDataHeader( { conditional : function() {
|
|
|
|
|
return (self.flags.value & BitmapFlag.BITMAP_COMPRESSION) && !(self.flags.value & BitmapFlag.NO_BITMAP_COMPRESSION_HDR);
|
|
|
|
|
} }),
|
|
|
|
|
bitmapDataStream : new type.BinaryString(coord.data, { readLength : new type.CallableValue(function() {
|
|
|
|
|
if(!self.flags.value & BitmapFlag.BITMAP_COMPRESSION || (self.flags.value & BitmapFlag.NO_BITMAP_COMPRESSION_HDR)) {
|
|
|
|
|
return self.bitmapLength.value;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return self.bitmapComprHdr.cbCompMainBodySize.value;
|
|
|
|
|
}
|
|
|
|
|
}) })
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/dd306368.aspx
|
|
|
|
|
* @param data {type.Component} list of bitmap data type
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function bitmapUpdateDataPDU(data, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__UPDATE_TYPE__ : UpdateType.UPDATETYPE_BITMAP,
|
|
|
|
|
numberRectangles : new type.UInt16Le(function() {
|
|
|
|
|
return self.rectangles.obj.length;
|
|
|
|
|
}),
|
|
|
|
|
rectangles : data || new type.Factory(function(s) {
|
|
|
|
|
self.rectangles = new type.Component([]);
|
|
|
|
|
for(var i = 0; i < self.numberRectangles.value; i++) {
|
|
|
|
|
self.rectangles.obj.push(bitmapData().read(s));
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see https://msdn.microsoft.com/en-us/library/cc240613.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function synchronizeUpdateDataPDU(opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
pad2Octets : new type.UInt16Le()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240608.aspx
|
|
|
|
|
* @param updateData {type.Component} update data (ex: bitmapUpdateDataPDU)
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function updateDataPDU(updateData, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE2_ : PDUType2.PDUTYPE2_UPDATE__,
|
|
|
|
|
updateType : new type.UInt16Le(function() {
|
|
|
|
|
return self.updateData.obj.__UPDATE_TYPE__;
|
|
|
|
|
}),
|
|
|
|
|
updateData : updateData || new type.Factory(function(s) {
|
|
|
|
|
var options = { readLength : new type.CallableValue(function() {
|
|
|
|
|
return opt.readLength.value - 2;
|
|
|
|
|
})};
|
|
|
|
|
switch(self.updateType.value) {
|
|
|
|
|
case UpdateType.UPDATETYPE_BITMAP:
|
|
|
|
|
self.updateData = bitmapUpdateDataPDU(null, options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case UpdateType.UPDATETYPE_SYNCHRONIZE:
|
|
|
|
|
// do nothing artefact of protocol
|
|
|
|
|
self.updateData = synchronizeUpdateDataPDU(null, options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
self.updateData = new type.BinaryString(null, options).read(s);
|
|
|
|
|
log.debug('unknown updateDataPDU ' + self.updateType.value);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param pduData {type.Component}
|
|
|
|
|
* @param shareId {integer}
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function dataPDU(pduData, shareId, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__PDUTYPE__ : PDUType.PDUTYPE_DATAPDU,
|
|
|
|
|
shareDataHeader : shareDataHeader(new type.CallableValue(function() {
|
|
|
|
|
return new type.Component(self).size();
|
|
|
|
|
}), function() {
|
|
|
|
|
return self.pduData.obj.__PDUTYPE2__;
|
|
|
|
|
}, shareId),
|
|
|
|
|
pduData : pduData || new type.Factory(function(s) {
|
|
|
|
|
|
|
|
|
|
//compute local readLength
|
|
|
|
|
var options = { readLength : new type.CallableValue(function() {
|
|
|
|
|
return opt.readLength.value - self.shareDataHeader.size();
|
|
|
|
|
}) };
|
|
|
|
|
|
|
|
|
|
switch(self.shareDataHeader.obj.pduType2.value) {
|
|
|
|
|
case PDUType2.PDUTYPE2_SYNCHRONIZE:
|
|
|
|
|
self.pduData = synchronizeDataPDU(null, options).read(s)
|
|
|
|
|
break;
|
|
|
|
|
case PDUType2.PDUTYPE2_CONTROL:
|
|
|
|
|
self.pduData = controlDataPDU(null, options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType2.PDUTYPE2_SET_ERROR_INFO_PDU:
|
|
|
|
|
self.pduData = errorInfoDataPDU(null, options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType2.PDUTYPE2_FONTLIST:
|
|
|
|
|
self.pduData = fontListDataPDU(options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType2.PDUTYPE2_FONTMAP:
|
|
|
|
|
self.pduData = fontMapDataPDU(options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType2.PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST:
|
|
|
|
|
self.pduData = persistentListPDU(null, options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType2.PDUTYPE2_INPUT:
|
|
|
|
|
self.pduData = clientInputEventPDU(null, options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType2.PDUTYPE2_SHUTDOWN_REQUEST:
|
|
|
|
|
self.pduData = shutdownRequestPDU(options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType2.PDUTYPE2_SHUTDOWN_DENIED:
|
|
|
|
|
self.pduData = shutdownDeniedPDU(options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType2.PDUTYPE2_SUPPRESS_OUTPUT:
|
|
|
|
|
self.pduData = supressOutputDataPDU(options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType2.PDUTYPE2_REFRESH_RECT:
|
|
|
|
|
self.pduData = refreshRectPDU(null, options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType2.PDUTYPE2_UPDATE:
|
|
|
|
|
self.pduData = updateDataPDU(null, options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
self.pduData = new type.BinaryString(null, options).read(s);
|
|
|
|
|
log.debug('unknown PDUType2 ' + self.shareDataHeader.obj.pduType2.value);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param userId {integer}
|
|
|
|
|
* @param pduMessage {type.Component} pdu message
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function pdu(userId, pduMessage, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
shareControlHeader : shareControlHeader(function() {
|
|
|
|
|
return new type.Component(self).size();
|
|
|
|
|
}, function() {
|
|
|
|
|
return pduMessage.obj.__PDUTYPE__;
|
|
|
|
|
}, userId),
|
|
|
|
|
pduMessage : pduMessage || new type.Factory(function(s) {
|
|
|
|
|
|
|
|
|
|
// compute local common options
|
|
|
|
|
var options = { readLength : new type.CallableValue(function() {
|
|
|
|
|
return self.shareControlHeader.obj.totalLength.value - self.shareControlHeader.size();
|
|
|
|
|
}) };
|
|
|
|
|
|
|
|
|
|
switch(self.shareControlHeader.obj.pduType.value) {
|
|
|
|
|
case PDUType.PDUTYPE_DEMANDACTIVEPDU:
|
|
|
|
|
self.pduMessage = demandActivePDU(null, options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType.PDUTYPE_CONFIRMACTIVEPDU:
|
|
|
|
|
self.pduMessage = confirmActivePDU(null, options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType.PDUTYPE_DEACTIVATEALLPDU:
|
|
|
|
|
self.pduMessage = deactiveAllPDU(options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
case PDUType.PDUTYPE_DATAPDU:
|
|
|
|
|
self.pduMessage = dataPDU(null, null, options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
self.pduMessage = new type.BinaryString(null, options).read(s);
|
|
|
|
|
log.debug('unknown pdu type ' + self.shareControlHeader.obj.pduType.value);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-15 02:00:57 -04:00
|
|
|
|
|
|
|
|
|
const ClipPDUMsgType = {
|
|
|
|
|
CB_MONITOR_READY: 0x0001,
|
|
|
|
|
CB_FORMAT_LIST: 0x0002,
|
|
|
|
|
CB_FORMAT_LIST_RESPONSE: 0x0003,
|
|
|
|
|
CB_FORMAT_DATA_REQUEST: 0x0004,
|
|
|
|
|
CB_FORMAT_DATA_RESPONSE: 0x0005,
|
|
|
|
|
CB_TEMP_DIRECTORY: 0x0006,
|
|
|
|
|
CB_CLIP_CAPS: 0x0007,
|
|
|
|
|
CB_FILECONTENTS_REQUEST: 0x0008
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function clipPDU() {
|
|
|
|
|
const self = {
|
|
|
|
|
header: new type.Factory(function (s) {
|
|
|
|
|
self.header = new type.Component({
|
|
|
|
|
msgType: new type.UInt16Le().read(s),
|
|
|
|
|
msgFlags: new type.UInt16Le().read(s),
|
|
|
|
|
dataLen: new type.UInt32Le().read(s)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return new type.Component(self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-04-29 14:13:58 -04:00
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/dd306368.aspx
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function fastPathBitmapUpdateDataPDU (opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
__FASTPATH_UPDATE_TYPE__ : FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP,
|
|
|
|
|
header : new type.UInt16Le(FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP, { constant : true }),
|
|
|
|
|
numberRectangles : new type.UInt16Le( function () {
|
|
|
|
|
return self.rectangles.obj.length;
|
|
|
|
|
}),
|
|
|
|
|
rectangles : new type.Factory( function (s) {
|
|
|
|
|
self.rectangles = new type.Component([]);
|
|
|
|
|
for(var i = 0; i < self.numberRectangles.value; i++) {
|
|
|
|
|
self.rectangles.obj.push(bitmapData().read(s));
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @see http://msdn.microsoft.com/en-us/library/cc240622.aspx
|
|
|
|
|
* @param updateData {type.Component}
|
|
|
|
|
* @param opt {object} type option
|
|
|
|
|
* @returns {type.Component}
|
|
|
|
|
*/
|
|
|
|
|
function fastPathUpdatePDU (updateData, opt) {
|
|
|
|
|
var self = {
|
|
|
|
|
updateHeader : new type.UInt8( function () {
|
|
|
|
|
return self.updateData.obj.__FASTPATH_UPDATE_TYPE__;
|
|
|
|
|
}),
|
|
|
|
|
compressionFlags : new type.UInt8(null, { conditional : function () {
|
|
|
|
|
return (self.updateHeader.value >> 4) & FastPathOutputCompression.FASTPATH_OUTPUT_COMPRESSION_USED;
|
|
|
|
|
}}),
|
|
|
|
|
size : new type.UInt16Le( function () {
|
|
|
|
|
return self.updateData.size();
|
|
|
|
|
}),
|
|
|
|
|
updateData : updateData || new type.Factory( function (s) {
|
|
|
|
|
var options = { readLength : new type.CallableValue( function () {
|
|
|
|
|
return self.size.value;
|
|
|
|
|
}) };
|
|
|
|
|
|
|
|
|
|
switch (self.updateHeader.value & 0xf) {
|
|
|
|
|
case FastPathUpdateType.FASTPATH_UPDATETYPE_BITMAP:
|
|
|
|
|
self.updateData = fastPathBitmapUpdateDataPDU(options).read(s);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
self.updateData = new type.BinaryString(null, options).read(s);
|
|
|
|
|
log.debug('unknown fast path pdu type ' + (self.updateHeader.value & 0xf));
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return new type.Component(self, opt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Module exports
|
|
|
|
|
*/
|
|
|
|
|
module.exports = {
|
|
|
|
|
PDUType : PDUType,
|
|
|
|
|
PDUType2 : PDUType2,
|
|
|
|
|
StreamId : StreamId,
|
|
|
|
|
CompressionOrder : CompressionOrder,
|
|
|
|
|
CompressionType : CompressionType,
|
|
|
|
|
Action : Action,
|
|
|
|
|
PersistentKeyListFlag : PersistentKeyListFlag,
|
|
|
|
|
BitmapFlag : BitmapFlag,
|
|
|
|
|
UpdateType : UpdateType,
|
|
|
|
|
InputMessageType : InputMessageType,
|
|
|
|
|
PointerFlag : PointerFlag,
|
|
|
|
|
KeyboardFlag : KeyboardFlag,
|
|
|
|
|
FastPathOutputCompression : FastPathOutputCompression,
|
|
|
|
|
Display : Display,
|
|
|
|
|
ToogleFlag : ToogleFlag,
|
|
|
|
|
ErrorInfo : ErrorInfo,
|
|
|
|
|
FastPathUpdateType : FastPathUpdateType,
|
|
|
|
|
shareControlHeader : shareControlHeader,
|
|
|
|
|
shareDataHeader : shareDataHeader,
|
|
|
|
|
demandActivePDU : demandActivePDU,
|
|
|
|
|
confirmActivePDU : confirmActivePDU,
|
|
|
|
|
deactiveAllPDU : deactiveAllPDU,
|
|
|
|
|
pdu : pdu,
|
|
|
|
|
synchronizeDataPDU : synchronizeDataPDU,
|
|
|
|
|
controlDataPDU : controlDataPDU,
|
|
|
|
|
errorInfoDataPDU : errorInfoDataPDU,
|
|
|
|
|
fontListDataPDU : fontListDataPDU,
|
|
|
|
|
fontMapDataPDU : fontMapDataPDU,
|
|
|
|
|
persistentListPDU : persistentListPDU,
|
|
|
|
|
synchronizeEvent : synchronizeEvent,
|
|
|
|
|
pointerEvent : pointerEvent,
|
|
|
|
|
scancodeKeyEvent : scancodeKeyEvent,
|
|
|
|
|
unicodeKeyEvent : unicodeKeyEvent,
|
|
|
|
|
slowPathInputEvent : slowPathInputEvent,
|
|
|
|
|
clientInputEventPDU : clientInputEventPDU,
|
|
|
|
|
shutdownRequestPDU : shutdownRequestPDU,
|
|
|
|
|
shutdownDeniedPDU : shutdownDeniedPDU,
|
|
|
|
|
supressOutputDataPDU : supressOutputDataPDU,
|
|
|
|
|
refreshRectPDU : refreshRectPDU,
|
|
|
|
|
bitmapData : bitmapData,
|
|
|
|
|
bitmapUpdateDataPDU : bitmapUpdateDataPDU,
|
|
|
|
|
updateDataPDU : updateDataPDU,
|
|
|
|
|
dataPDU : dataPDU,
|
|
|
|
|
fastPathBitmapUpdateDataPDU : fastPathBitmapUpdateDataPDU,
|
2022-05-15 02:00:57 -04:00
|
|
|
|
fastPathUpdatePDU: fastPathUpdatePDU,
|
|
|
|
|
clipPDU: clipPDU,
|
|
|
|
|
ClipPDUMsgType: ClipPDUMsgType
|
2022-04-29 14:13:58 -04:00
|
|
|
|
};
|