892 lines
27 KiB
C
892 lines
27 KiB
C
/*
|
|
FreeRDP: A Remote Desktop Protocol Implementation
|
|
RAIL(TS RemoteApp) Virtual Channel Unit Tests
|
|
|
|
Copyright 2011 Vic Lee
|
|
Copyright 2011 Roman Barabanov <romanbarabanov@gmail.com>
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <pthread.h>
|
|
|
|
#include <freerdp/freerdp.h>
|
|
#include <freerdp/constants.h>
|
|
#include <freerdp/channels/channels.h>
|
|
#include <freerdp/utils/event.h>
|
|
#include <freerdp/utils/hexdump.h>
|
|
#include <freerdp/utils/memory.h>
|
|
#include <freerdp/utils/rail.h>
|
|
#include <freerdp/rail.h>
|
|
|
|
|
|
#include "test_rail.h"
|
|
|
|
#define HCF_HIGHCONTRASTON 0x00000001
|
|
#define HCF_AVAILABLE 0x00000002
|
|
#define HCF_HOTKEYACTIVE 0x00000004
|
|
#define HCF_CONFIRMHOTKEY 0x00000008
|
|
#define HCF_HOTKEYSOUND 0x00000010
|
|
#define HCF_INDICATOR 0x00000020
|
|
#define HCF_HOTKEYAVAILABLE 0x00000040
|
|
|
|
|
|
int init_rail_suite(void)
|
|
{
|
|
freerdp_channels_global_init();
|
|
return 0;
|
|
}
|
|
|
|
int clean_rail_suite(void)
|
|
{
|
|
freerdp_channels_global_uninit();
|
|
return 0;
|
|
}
|
|
|
|
int add_rail_suite(void)
|
|
{
|
|
add_test_suite(rail);
|
|
|
|
add_test_function(rail_plugin);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static BYTE client_handshake[] =
|
|
{
|
|
0x05, 0x00, 0x08, 0x00, 0xb0, 0x1d, 0x00, 0x00
|
|
};
|
|
|
|
static BYTE client_info_pdu[] =
|
|
{
|
|
0x0b, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
// Flags: TS_RAIL_EXEC_FLAG_EXPAND_ARGUMENTS
|
|
// ExeOrFile : ||iexplore
|
|
// WorkingDir: f:\windows\system32
|
|
// Arguments: www.bing.com
|
|
|
|
static BYTE client_execute_pdu[] =
|
|
{
|
|
0x01,0x00,0x5e,0x00,0x08,0x00,0x14,0x00,0x26,0x00,0x18,0x00,0x7c,0x00,
|
|
0x7c,0x00,0x69,0x00,0x65,0x00,0x78,0x00,0x70,0x00,0x6c,0x00,0x6f,0x00,
|
|
0x72,0x00,0x65,0x00,0x66,0x00,0x3a,0x00,0x5c,0x00,0x77,0x00,0x69,0x00,
|
|
0x6e,0x00,0x64,0x00,0x6f,0x00,0x77,0x00,0x73,0x00,0x5c,0x00,0x73,0x00,
|
|
0x79,0x00,0x73,0x00,0x74,0x00,0x65,0x00,0x6d,0x00,0x33,0x00,0x32,0x00,
|
|
0x77,0x00,0x77,0x00,0x77,0x00,0x2e,0x00,0x62,0x00,0x69,0x00,0x6e,0x00,
|
|
0x67,0x00,0x2e,0x00,0x63,0x00,0x6f,0x00,0x6d,0x00
|
|
};
|
|
|
|
static BYTE client_activate_pdu[] =
|
|
{
|
|
0x02,0x00,
|
|
0x09,0x00,
|
|
0x8e,0x00,0x07,0x00,
|
|
0x01
|
|
};
|
|
|
|
|
|
|
|
static BYTE client_sysparam_highcontrast_pdu[] =
|
|
{
|
|
0x03,0x00,
|
|
0x12,0x00,
|
|
0x43,0x00,0x00,0x00, // SPI_SETHIGHCONTRAST
|
|
0x7e,0x00,0x00,0x00, // HCF_AVAILABLE | HCF_HOTKEYACTIVE | HCF_CONFIRMHOTKEY
|
|
// HCF_HOTKEYSOUND | HCF_INDICATOR | HCF_HOTKEYAVAILABLE
|
|
0x02,0x00,0x00,0x00, // Minimum length 2
|
|
0x00,0x00 // Unicode String
|
|
};
|
|
|
|
|
|
static BYTE client_sysparam_taskbarpos_pdu[] =
|
|
{
|
|
0x03,0x00,
|
|
0x10,0x00,
|
|
0x00,0xf0,0x00,0x00, // RAIL_SPI_TASKBARPOS
|
|
0x00,0x00, // 0
|
|
0x9a,0x03, // 0x039a
|
|
0x90,0x06, // 0x0690
|
|
0xc2,0x03 // 0x03c2
|
|
};
|
|
|
|
static BYTE client_sysparam_mousebuttonswap_pdu[] =
|
|
{
|
|
0x03,0x00,
|
|
0x09,0x00,
|
|
0x21,0x00,0x00,0x00, // SPI_SETMOUSEBUTTONSWAP
|
|
0x00 // FALSE
|
|
};
|
|
|
|
|
|
static BYTE client_sysparam_keyboardpref_pdu[] =
|
|
{
|
|
0x03,0x00,
|
|
0x09,0x00,
|
|
0x45,0x00,0x00,0x00, // SPI_SETKEYBOARDPREF
|
|
0x00 // FALSE
|
|
};
|
|
|
|
|
|
static BYTE client_sysparam_dragfullwindow_pdu[] =
|
|
{
|
|
0x03,0x00,
|
|
0x09,0x00,
|
|
0x25,0x00,0x00,0x00, // SPI_SETDRAGFULLWINDOWS
|
|
0x01 // TRUE
|
|
};
|
|
|
|
|
|
static BYTE client_sysparam_keyboardcues_pdu[] =
|
|
{
|
|
0x03,0x00,
|
|
0x09,0x00,
|
|
0x0b,0x10,0x00,0x00, //SPI_SETKEYBOARDCUES
|
|
0x00 // FALSE
|
|
};
|
|
|
|
static BYTE client_sysparam_setworkarea_pdu[] =
|
|
{
|
|
0x03,0x00,
|
|
0x10,0x00,
|
|
0x2f,0x00,0x00,0x00, //SPI_SETWORKAREA
|
|
0x00,0x00, // 0
|
|
0x00,0x00, // 0
|
|
0x90,0x06, // 0x0690
|
|
0x9a,0x03 // 0x039a
|
|
};
|
|
|
|
static BYTE client_syscommand_pdu[] =
|
|
{
|
|
0x04,0x00,
|
|
0x0a,0x00,
|
|
0x52,0x00,0x02,0x00,
|
|
0x20,0xf0
|
|
};
|
|
|
|
static BYTE client_notify_pdu[] =
|
|
{
|
|
0x06,0x00,
|
|
0x10,0x00,
|
|
0xaa,0x01,0x02,0x00,
|
|
0x02,0x00,0x00,0x00,
|
|
0x04,0x02,0x00,0x00
|
|
};
|
|
|
|
static BYTE client_windowmove_pdu[] =
|
|
{
|
|
0x08,0x00,
|
|
0x10,0x00,
|
|
0x20,0x00,0x02,0x00,
|
|
0x09,0x03,
|
|
0x00,0x01,
|
|
0xdb,0x05,
|
|
0x88,0x01
|
|
};
|
|
|
|
static BYTE client_system_menu_pdu[] =
|
|
{
|
|
0x0c,0x00,
|
|
0x0c,0x00,
|
|
0x22,0x01,0x09,0x00,
|
|
0xa4,0xff,
|
|
0x4a,0x02
|
|
};
|
|
|
|
static BYTE client_langbar_pdu[] =
|
|
{
|
|
0x0D,0x00,0x08,0x00,0x01,0x00,0x00,0x00
|
|
};
|
|
|
|
static BYTE client_get_app_id_req_pdu[] =
|
|
{
|
|
0x0E,0x00,0x08,0x00,0x52,0x00,0x02,0x00
|
|
};
|
|
|
|
static BYTE server_handshake[] =
|
|
{
|
|
0x05, 0x00, 0x08, 0x00, 0xb0, 0x1d, 0x00, 0x00
|
|
};
|
|
|
|
static BYTE server_exec_result_pdu[] =
|
|
{
|
|
0x80,0x00,0x24,0x00,0x08,0x00,0x03,0x00,0x15,0x00,0x00,0x00,0x00,0x00,
|
|
0x14,0x00,0x7c,0x00,0x7c,0x00,0x57,0x00,0x72,0x00,0x6f,0x00,0x6e,0x00,
|
|
0x67,0x00,0x41,0x00,0x70,0x00,0x70,0x00
|
|
};
|
|
|
|
static BYTE server_exec_result_exe_or_file[] =
|
|
{
|
|
0x7c,0x00,0x7c,0x00,0x57,0x00,0x72,0x00,0x6f,0x00,0x6e,0x00,
|
|
0x67,0x00,0x41,0x00,0x70,0x00,0x70,0x00
|
|
};
|
|
|
|
static BYTE server_sysparam1_pdu[] =
|
|
{
|
|
0x03,0x00,
|
|
0x09,0x00,
|
|
0x77,0x00,0x00,0x00,
|
|
0x00
|
|
};
|
|
|
|
static BYTE server_sysparam2_pdu[] =
|
|
{
|
|
0x03,0x00,
|
|
0x09,0x00,
|
|
0x11,0x00,0x00,0x00,
|
|
0x00
|
|
};
|
|
|
|
static BYTE server_localmovesize_start_pdu[] =
|
|
{
|
|
0x09,0x00,0x10,0x00,0x8e,0x00,0x07,0x00,0x01,0x00,0x09,0x00,0x7e,0x01,
|
|
0x0a,0x00
|
|
};
|
|
|
|
static BYTE server_localmovesize_stop_pdu[] =
|
|
{
|
|
0x09,0x00,0x10,0x00,0x8e,0x00,0x07,0x00,0x00,0x00,0x09,0x00,0xa6,0x00,
|
|
0x44,0x00
|
|
};
|
|
|
|
static BYTE server_minmaxinfo_pdu[] =
|
|
{
|
|
0x0a,0x00,0x18,0x00,0x8e,0x00,0x07,0x00,0x08,0x04,0xd6,0x02,0x00,0x00,
|
|
0x00,0x00,0x70,0x00,0x1b,0x00,0x0c,0x04,0x0c,0x03
|
|
};
|
|
|
|
static BYTE server_langbar_pdu[] =
|
|
{
|
|
0x0D,0x00,0x08,0x00,0x01,0x00,0x00,0x00
|
|
};
|
|
|
|
|
|
static BYTE server_app_get_resp_pdu[] =
|
|
{
|
|
0x0F,0x00,0x08,0x02,0x52,0x00,0x02,0x00,0x6d,0x00,0x69,0x00,0x63,0x00,
|
|
0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x2e,0x00,
|
|
0x77,0x00,0x69,0x00,0x6e,0x6f,0x00,0x77,0x00,0x73,0x00,0x2e,0x00,0x6e,
|
|
0x00,0x6f,0x00,0x74,0x00,0x65,0x00,0x70,0x00,0x61,0x00,0x64,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,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,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,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,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,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,
|
|
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 server_app_get_resp_app_id[] =
|
|
{
|
|
0x6d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,
|
|
0x66,0x00,0x74,0x00,0x2e,0x00,0x77,0x00,0x69,0x00,0x6e,0x6f,0x00,0x77,
|
|
0x00,0x73,0x00,0x2e,0x00,0x6e,0x00,0x6f,0x00,0x74,0x00,0x65,0x00,0x70,
|
|
0x00,0x61,0x00,0x64,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,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,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,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,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,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,
|
|
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
|
|
};
|
|
|
|
|
|
#define EMULATE_SERVER_SEND_CHANNEL_DATA(inst, byte_array) \
|
|
emulate_server_send_channel_data(inst, byte_array, ARRAY_SIZE(byte_array))
|
|
|
|
#define STREAM_EQUAL_TO_DUMP(stream, dump) \
|
|
(stream_equal_dump((stream)->data, (stream)->size, dump, ARRAY_SIZE(dump)))
|
|
|
|
#define UNICODE_STRING_EQUAL_TO_DUMP(ustring, dump) \
|
|
(stream_equal_dump((ustring)->string, (ustring)->length, dump, ARRAY_SIZE(dump)))
|
|
|
|
typedef struct
|
|
{
|
|
RAIL_HANDSHAKE_ORDER handshake;
|
|
RAIL_CLIENT_STATUS_ORDER client_status;
|
|
RAIL_EXEC_ORDER exec;
|
|
RAIL_EXEC_RESULT_ORDER exec_result;
|
|
RAIL_SYSPARAM_ORDER sysparam;
|
|
RAIL_ACTIVATE_ORDER activate;
|
|
RAIL_SYSMENU_ORDER sysmenu;
|
|
RAIL_SYSCOMMAND_ORDER syscommand;
|
|
RAIL_NOTIFY_EVENT_ORDER notify_event;
|
|
RAIL_MINMAXINFO_ORDER minmaxinfo;
|
|
RAIL_LOCALMOVESIZE_ORDER localmovesize;
|
|
RAIL_WINDOW_MOVE_ORDER window_move;
|
|
RAIL_LANGBAR_INFO_ORDER langbar_info;
|
|
RAIL_GET_APPID_REQ_ORDER get_appid_req;
|
|
RAIL_GET_APPID_RESP_ORDER get_appid_resp;
|
|
|
|
} RAIL_ORDERS;
|
|
|
|
typedef struct
|
|
{
|
|
RAIL_ORDERS order_info;
|
|
UINT32 event_type;
|
|
}
|
|
RAIL_EVENT;
|
|
|
|
typedef struct
|
|
{
|
|
rdpChannels* chan_man;
|
|
freerdp* instance;
|
|
int th_count;
|
|
int th_to_finish;
|
|
|
|
RAIL_ORDERS out_rail_orders;
|
|
|
|
RAIL_EVENT in_events[20];
|
|
size_t in_events_number;
|
|
|
|
STREAM in_streams[20];
|
|
size_t in_streams_number;
|
|
|
|
RDP_PLUGIN_DATA plugin_data;
|
|
|
|
|
|
} thread_param;
|
|
|
|
static thread_param* global_thread_params = NULL;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
int stream_equal_dump(void * dataS, size_t sizeS, void * data, size_t size)
|
|
{
|
|
size_t i;
|
|
if (sizeS != size)
|
|
{
|
|
printf("----------------- stream_equal_dump -----------------\n");
|
|
printf("Stream and dump have different length (%d != %d)\n",
|
|
(int) sizeS, (int) size);
|
|
printf("Stream hexdump:\n");
|
|
freerdp_hexdump(dataS, sizeS);
|
|
|
|
printf("Dump hexdump:\n");
|
|
freerdp_hexdump(data, size);
|
|
|
|
printf("----------------- stream_equal_dump -----------------\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
for (i=0; i < size; i++)
|
|
{
|
|
if (((BYTE*)dataS)[i] != ((BYTE*)data)[i])
|
|
{
|
|
printf("----------------- stream_equal_dump -----------------\n");
|
|
printf("Stream and dump have different content from %d offset.\n", (int) i);
|
|
printf("Stream hexdump:\n");
|
|
freerdp_hexdump(dataS, sizeS);
|
|
|
|
printf("Dump hexdump:\n");
|
|
freerdp_hexdump(data, size);
|
|
printf("----------------- stream_equal_dump -----------------\n");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
static void test_on_free_rail_client_event(RDP_EVENT* event)
|
|
{
|
|
if (event->event_class == RDP_EVENT_CLASS_RAIL)
|
|
{
|
|
rail_free_cloned_order(event->event_type, event->user_data);
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
static void send_ui_event2plugin(
|
|
rdpChannels* chan_man,
|
|
UINT16 event_type,
|
|
void * data
|
|
)
|
|
{
|
|
RDP_EVENT* out_event = NULL;
|
|
void * payload = NULL;
|
|
|
|
payload = rail_clone_order(event_type, data);
|
|
if (payload != NULL)
|
|
{
|
|
out_event = freerdp_event_new(RDP_EVENT_CLASS_RAIL, event_type,
|
|
test_on_free_rail_client_event, payload);
|
|
freerdp_channels_send_event(chan_man, out_event);
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
static void emulate_server_send_channel_data(
|
|
freerdp* instance,
|
|
void* data,
|
|
size_t size
|
|
)
|
|
{
|
|
static int counter = 0;
|
|
counter++;
|
|
|
|
printf("Emulate server packet (%d packet):\n", counter);
|
|
freerdp_hexdump(data, size);
|
|
|
|
freerdp_channels_data(instance, 0, (char*)data, size,
|
|
CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST, size);
|
|
usleep(10*1000);
|
|
}
|
|
static void save_dump(void* data, size_t size)
|
|
{
|
|
thread_param * p = global_thread_params;
|
|
if (p->in_streams_number < ARRAY_SIZE(p->in_streams))
|
|
{
|
|
STREAM* s = &p->in_streams[p->in_streams_number];
|
|
s->data = malloc(size);
|
|
s->size = size;
|
|
|
|
memcpy(s->data, data, size);
|
|
p->in_streams_number++;
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
static int emulate_client_send_channel_data(
|
|
freerdp* freerdp, int channelId, BYTE* data, int size
|
|
)
|
|
{
|
|
static int counter = 0;
|
|
counter++;
|
|
|
|
printf("Client send to server (%d packet):\n", counter);
|
|
freerdp_hexdump(data, size);
|
|
|
|
// add to global dumps list
|
|
save_dump(data, size);
|
|
|
|
return 0;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
void save_event(RDP_EVENT* event, RAIL_EVENT* rail_event)
|
|
{
|
|
rail_event->event_type = event->event_type;
|
|
|
|
switch (event->event_type)
|
|
{
|
|
case RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS:
|
|
printf("UI receive Get Sysparams Event\n");
|
|
break;
|
|
|
|
case RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS:
|
|
{
|
|
RAIL_EXEC_RESULT_ORDER* exec_result = (RAIL_EXEC_RESULT_ORDER*)event->user_data;
|
|
printf("UI receive Exec Results Event\n");
|
|
memcpy(&rail_event->order_info.exec_result, event->user_data,
|
|
sizeof(RAIL_EXEC_RESULT_ORDER));
|
|
|
|
rail_unicode_string_alloc(&rail_event->order_info.exec_result.exeOrFile,
|
|
exec_result->exeOrFile.length);
|
|
|
|
memcpy(rail_event->order_info.exec_result.exeOrFile.string,
|
|
exec_result->exeOrFile.string,
|
|
exec_result->exeOrFile.length);
|
|
}
|
|
break;
|
|
|
|
case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM:
|
|
printf("UI receive Server Sysparam Event\n");
|
|
memcpy(&rail_event->order_info.sysparam, event->user_data,
|
|
sizeof(RAIL_SYSPARAM_ORDER));
|
|
break;
|
|
|
|
case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO:
|
|
printf("UI receive Server Minmax Info Event\n");
|
|
memcpy(&rail_event->order_info.minmaxinfo, event->user_data,
|
|
sizeof(RAIL_MINMAXINFO_ORDER));
|
|
break;
|
|
|
|
case RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE:
|
|
printf("UI receive Server Local Movesize Event\n");
|
|
memcpy(&rail_event->order_info.localmovesize, event->user_data,
|
|
sizeof(RAIL_LOCALMOVESIZE_ORDER));
|
|
break;
|
|
|
|
case RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP:
|
|
printf("UI receive AppId Response Event\n");
|
|
memcpy(&rail_event->order_info.get_appid_resp, event->user_data,
|
|
sizeof(RAIL_GET_APPID_RESP_ORDER));
|
|
|
|
rail_event->order_info.get_appid_resp.applicationId.string =
|
|
&rail_event->order_info.get_appid_resp.applicationIdBuffer[0];
|
|
break;
|
|
|
|
case RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO:
|
|
printf("UI receive Language Info Event\n");
|
|
memcpy(&rail_event->order_info.langbar_info, event->user_data,
|
|
sizeof(RAIL_LANGBAR_INFO_ORDER));
|
|
break;
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
static void process_events_and_channel_data_from_plugin(thread_param* param)
|
|
{
|
|
RDP_EVENT* event;
|
|
|
|
param->th_count++;
|
|
while (param->th_to_finish == 0)
|
|
{
|
|
freerdp_channels_check_fds(param->chan_man, param->instance);
|
|
|
|
while (1)
|
|
{
|
|
event = freerdp_channels_pop_event(param->chan_man);
|
|
if (event == NULL) break;
|
|
|
|
static int counter = 0;
|
|
counter++;
|
|
|
|
printf("UI receive event. (type=%d counter=%d).\n",
|
|
event->event_type,
|
|
counter);
|
|
|
|
// add to global event list
|
|
if (param->in_events_number < ARRAY_SIZE(param->in_events))
|
|
{
|
|
save_event(event, ¶m->in_events[param->in_events_number]);
|
|
param->in_events_number++;
|
|
}
|
|
freerdp_event_free(event);
|
|
}
|
|
|
|
usleep(1000);
|
|
}
|
|
param->th_count--;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
void* thread_func(void* param)
|
|
{
|
|
thread_param* th_param = (thread_param*)param;
|
|
process_events_and_channel_data_from_plugin(th_param);
|
|
pthread_detach(pthread_self());
|
|
|
|
return NULL;
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
void test_rail_plugin(void)
|
|
{
|
|
thread_param param;
|
|
pthread_t thread;
|
|
|
|
rdpChannels* chan_man;
|
|
rdpSettings settings = { 0 };
|
|
freerdp s_inst = { 0 };
|
|
freerdp* inst = &s_inst;
|
|
size_t sn = 0;
|
|
size_t en = 0;
|
|
STREAM* ss = NULL;
|
|
RAIL_EVENT* ee = NULL;
|
|
|
|
printf("\n");
|
|
|
|
settings.hostname = "testhost";
|
|
inst->settings = &settings;
|
|
inst->SendChannelData = emulate_client_send_channel_data;
|
|
|
|
chan_man = freerdp_channels_new();
|
|
|
|
freerdp_channels_load_plugin(chan_man, &settings, "../channels/rail/rail.so", NULL);
|
|
freerdp_channels_pre_connect(chan_man, inst);
|
|
freerdp_channels_post_connect(chan_man, inst);
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.chan_man = chan_man;
|
|
param.instance = inst;
|
|
param.th_count = 0;
|
|
param.th_to_finish = 0;
|
|
|
|
global_thread_params = ¶m;
|
|
|
|
pthread_create(&thread, 0, thread_func, ¶m);
|
|
|
|
// 1. Emulate server handshake binary
|
|
EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_handshake);
|
|
EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_exec_result_pdu);
|
|
EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_sysparam1_pdu);
|
|
EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_sysparam2_pdu);
|
|
EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_localmovesize_start_pdu);
|
|
EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_localmovesize_stop_pdu);
|
|
EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_minmaxinfo_pdu);
|
|
EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_langbar_pdu);
|
|
EMULATE_SERVER_SEND_CHANNEL_DATA(inst, server_app_get_resp_pdu);
|
|
|
|
// 2. Send UI events
|
|
|
|
param.out_rail_orders.sysparam.params = 0;
|
|
|
|
param.out_rail_orders.sysparam.params |= SPI_MASK_SET_HIGH_CONTRAST;
|
|
param.out_rail_orders.sysparam.highContrast.flags = 0x7e;
|
|
param.out_rail_orders.sysparam.highContrast.colorScheme.length = 0;
|
|
param.out_rail_orders.sysparam.highContrast.colorScheme.string = NULL;
|
|
|
|
param.out_rail_orders.sysparam.params |= SPI_MASK_TASKBAR_POS;
|
|
param.out_rail_orders.sysparam.taskbarPos.left = 0;
|
|
param.out_rail_orders.sysparam.taskbarPos.top = 0x039a;
|
|
param.out_rail_orders.sysparam.taskbarPos.right = 0x0690;
|
|
param.out_rail_orders.sysparam.taskbarPos.bottom = 0x03c2;
|
|
|
|
param.out_rail_orders.sysparam.params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP;
|
|
param.out_rail_orders.sysparam.mouseButtonSwap = FALSE;
|
|
|
|
param.out_rail_orders.sysparam.params |= SPI_MASK_SET_KEYBOARD_PREF;
|
|
param.out_rail_orders.sysparam.keyboardPref = FALSE;
|
|
|
|
param.out_rail_orders.sysparam.params |= SPI_MASK_SET_DRAG_FULL_WINDOWS;
|
|
param.out_rail_orders.sysparam.dragFullWindows = TRUE;
|
|
|
|
param.out_rail_orders.sysparam.params |= SPI_MASK_SET_KEYBOARD_CUES;
|
|
param.out_rail_orders.sysparam.keyboardCues = FALSE;
|
|
|
|
param.out_rail_orders.sysparam.params |= SPI_MASK_SET_WORK_AREA;
|
|
param.out_rail_orders.sysparam.workArea.left = 0;
|
|
param.out_rail_orders.sysparam.workArea.top = 0;
|
|
param.out_rail_orders.sysparam.workArea.right = 0x0690;
|
|
param.out_rail_orders.sysparam.workArea.bottom = 0x039a;
|
|
|
|
send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_SET_SYSPARAMS,
|
|
¶m.out_rail_orders.sysparam);
|
|
|
|
param.plugin_data.size = sizeof(RDP_PLUGIN_DATA);
|
|
param.plugin_data.data[0] = "||iexplore";
|
|
param.plugin_data.data[1] = "f:\\windows\\system32";
|
|
param.plugin_data.data[2] = "www.bing.com";
|
|
send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_EXEC_REMOTE_APP,
|
|
¶m.plugin_data);
|
|
|
|
param.out_rail_orders.activate.enabled = TRUE;
|
|
param.out_rail_orders.activate.windowId = 0x0007008e;
|
|
send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_ACTIVATE,
|
|
¶m.out_rail_orders.activate);
|
|
|
|
param.out_rail_orders.syscommand.windowId = 0x00020052;
|
|
param.out_rail_orders.syscommand.command = 0xf020;
|
|
send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_SYSCOMMAND,
|
|
¶m.out_rail_orders.syscommand);
|
|
|
|
param.out_rail_orders.notify_event.windowId = 0x000201aa;
|
|
param.out_rail_orders.notify_event.notifyIconId = 0x02;
|
|
param.out_rail_orders.notify_event.message = 0x0204;
|
|
send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_NOTIFY_EVENT,
|
|
¶m.out_rail_orders.notify_event);
|
|
|
|
|
|
param.out_rail_orders.window_move.windowId = 0x00020020;
|
|
param.out_rail_orders.window_move.left = 0x0309;
|
|
param.out_rail_orders.window_move.top = 0x0100;
|
|
param.out_rail_orders.window_move.right = 0x05db;
|
|
param.out_rail_orders.window_move.bottom = 0x0188;
|
|
send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE,
|
|
¶m.out_rail_orders.window_move);
|
|
|
|
param.out_rail_orders.sysmenu.windowId = 0x00090122;
|
|
param.out_rail_orders.sysmenu.left = 0xffa4; // TODO: possible negative values?
|
|
param.out_rail_orders.sysmenu.top = 0x024a;
|
|
send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_SYSMENU,
|
|
¶m.out_rail_orders.sysmenu);
|
|
|
|
param.out_rail_orders.langbar_info.languageBarStatus = 0x00000001;
|
|
send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_LANGBARINFO,
|
|
¶m.out_rail_orders.langbar_info);
|
|
|
|
param.out_rail_orders.get_appid_req.windowId = 0x00020052;
|
|
send_ui_event2plugin(chan_man, RDP_EVENT_TYPE_RAIL_CLIENT_APPID_REQ,
|
|
¶m.out_rail_orders.get_appid_req);
|
|
|
|
// Waiting for possible events or data
|
|
sleep(1);
|
|
|
|
// Finishing thread and wait for it
|
|
param.th_to_finish = 1;
|
|
while (param.th_count > 0)
|
|
{
|
|
usleep(1000);
|
|
}
|
|
|
|
// We need to collected all events and data dumps and then to.
|
|
// create CU_ASSERT series here!
|
|
sn = param.in_streams_number;
|
|
en = param.in_events_number;
|
|
ss = ¶m.in_streams[0];
|
|
ee = ¶m.in_events[0];
|
|
|
|
CU_ASSERT(sn > 0 && STREAM_EQUAL_TO_DUMP(&ss[ 0], client_handshake));
|
|
CU_ASSERT(sn > 1 && STREAM_EQUAL_TO_DUMP(&ss[ 1], client_info_pdu));
|
|
CU_ASSERT(sn > 2 && STREAM_EQUAL_TO_DUMP(&ss[ 2], client_sysparam_highcontrast_pdu));
|
|
CU_ASSERT(sn > 3 && STREAM_EQUAL_TO_DUMP(&ss[ 3], client_sysparam_taskbarpos_pdu));
|
|
CU_ASSERT(sn > 4 && STREAM_EQUAL_TO_DUMP(&ss[ 4], client_sysparam_mousebuttonswap_pdu));
|
|
CU_ASSERT(sn > 5 && STREAM_EQUAL_TO_DUMP(&ss[ 5], client_sysparam_keyboardpref_pdu));
|
|
CU_ASSERT(sn > 6 && STREAM_EQUAL_TO_DUMP(&ss[ 6], client_sysparam_dragfullwindow_pdu));
|
|
CU_ASSERT(sn > 7 && STREAM_EQUAL_TO_DUMP(&ss[ 7], client_sysparam_keyboardcues_pdu));
|
|
CU_ASSERT(sn > 8 && STREAM_EQUAL_TO_DUMP(&ss[ 8], client_sysparam_setworkarea_pdu));
|
|
CU_ASSERT(sn > 9 && STREAM_EQUAL_TO_DUMP(&ss[ 9], client_execute_pdu));
|
|
CU_ASSERT(sn >10 && STREAM_EQUAL_TO_DUMP(&ss[10], client_activate_pdu));
|
|
CU_ASSERT(sn >11 && STREAM_EQUAL_TO_DUMP(&ss[11], client_syscommand_pdu));
|
|
CU_ASSERT(sn >12 && STREAM_EQUAL_TO_DUMP(&ss[12], client_notify_pdu));
|
|
CU_ASSERT(sn >13 && STREAM_EQUAL_TO_DUMP(&ss[13], client_windowmove_pdu));
|
|
CU_ASSERT(sn >14 && STREAM_EQUAL_TO_DUMP(&ss[14], client_system_menu_pdu));
|
|
CU_ASSERT(sn >15 && STREAM_EQUAL_TO_DUMP(&ss[15], client_langbar_pdu));
|
|
CU_ASSERT(sn >16 && STREAM_EQUAL_TO_DUMP(&ss[16], client_get_app_id_req_pdu));
|
|
|
|
CU_ASSERT(en > 0 && ee[ 0].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_GET_SYSPARAMS);
|
|
CU_ASSERT(en > 1 &&
|
|
ee[ 1].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_EXEC_RESULTS &&
|
|
ee[ 1].order_info.exec_result.flags == 0x08 &&
|
|
ee[ 1].order_info.exec_result.execResult == 0x03 &&
|
|
UNICODE_STRING_EQUAL_TO_DUMP(
|
|
&ee[ 1].order_info.exec_result.exeOrFile,
|
|
server_exec_result_exe_or_file)
|
|
);
|
|
CU_ASSERT(en > 2 &&
|
|
ee[ 2].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM &&
|
|
ee[ 2].order_info.sysparam.setScreenSaveSecure == FALSE
|
|
);
|
|
|
|
CU_ASSERT(en > 3 &&
|
|
ee[ 3].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_SYSPARAM &&
|
|
ee[ 3].order_info.sysparam.setScreenSaveActive == FALSE
|
|
);
|
|
|
|
CU_ASSERT(en > 4 &&
|
|
ee[ 4].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE &&
|
|
ee[ 4].order_info.localmovesize.windowId == 0x0007008e &&
|
|
ee[ 4].order_info.localmovesize.isMoveSizeStart == TRUE &&
|
|
ee[ 4].order_info.localmovesize.moveSizeType == RAIL_WMSZ_MOVE &&
|
|
ee[ 4].order_info.localmovesize.posX == 0x017e &&
|
|
ee[ 4].order_info.localmovesize.posY == 0x000a
|
|
);
|
|
|
|
CU_ASSERT(en > 5 &&
|
|
ee[ 5].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_LOCALMOVESIZE &&
|
|
ee[ 5].order_info.localmovesize.windowId == 0x0007008e &&
|
|
ee[ 5].order_info.localmovesize.isMoveSizeStart == FALSE &&
|
|
ee[ 5].order_info.localmovesize.moveSizeType == RAIL_WMSZ_MOVE &&
|
|
ee[ 5].order_info.localmovesize.posX == 0x00a6 &&
|
|
ee[ 5].order_info.localmovesize.posY == 0x0044
|
|
);
|
|
|
|
CU_ASSERT(en > 6 &&
|
|
ee[ 6].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_SERVER_MINMAXINFO &&
|
|
ee[ 6].order_info.minmaxinfo.windowId == 0x0007008e &&
|
|
ee[ 6].order_info.minmaxinfo.maxWidth == 0x0408 &&
|
|
ee[ 6].order_info.minmaxinfo.maxHeight == 0x02d6 &&
|
|
ee[ 6].order_info.minmaxinfo.maxPosX == 0x0000 &&
|
|
ee[ 6].order_info.minmaxinfo.maxPosY == 0x0000 &&
|
|
ee[ 6].order_info.minmaxinfo.minTrackWidth == 0x0070 &&
|
|
ee[ 6].order_info.minmaxinfo.minTrackHeight == 0x001b &&
|
|
ee[ 6].order_info.minmaxinfo.maxTrackWidth == 0x040c &&
|
|
ee[ 6].order_info.minmaxinfo.maxTrackHeight == 0x030c
|
|
);
|
|
|
|
CU_ASSERT(en > 7 &&
|
|
ee[ 7].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_LANGBARINFO &&
|
|
ee[ 7].order_info.langbar_info.languageBarStatus == TF_SFT_SHOWNORMAL
|
|
);
|
|
|
|
CU_ASSERT(en > 8 &&
|
|
ee[ 8].event_type == RDP_EVENT_TYPE_RAIL_CHANNEL_APPID_RESP &&
|
|
ee[ 8].order_info.get_appid_resp.windowId == 0x00020052 &&
|
|
UNICODE_STRING_EQUAL_TO_DUMP(
|
|
&ee[ 8].order_info.get_appid_resp.applicationId,
|
|
server_app_get_resp_app_id
|
|
)
|
|
);
|
|
|
|
freerdp_channels_close(chan_man, inst);
|
|
freerdp_channels_free(chan_man);
|
|
}
|
|
|
|
|
|
|
|
|