rail: removing older code

This commit is contained in:
Marc-André Moreau 2011-08-11 16:27:16 -04:00
parent 53981e9dba
commit 91326a4f65
9 changed files with 160 additions and 1441 deletions

View File

@ -19,14 +19,9 @@
set(RAIL_SRCS
rail_main.c
rail_main.h
rail_core.c
rail_core.h
rail_main.h
rail_orders.c
rail_orders.h
rail_channel_orders.c
rail_channel_orders.h
)
rail_orders.h)
add_library(rail SHARED ${RAIL_SRCS})
set_target_properties(rail PROPERTIES PREFIX "")

View File

@ -1,610 +0,0 @@
/*
FreeRDP: A Remote Desktop Protocol client.
Remote Applications Integrated Locally (RAIL)
Copyright 2009 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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 <stdlib.h>
#include <string.h>
#include <freerdp/constants.h>
#include <freerdp/types.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/stream.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/utils/rail.h>
#include <freerdp/rail.h>
#include "rail_core.h"
#include "rail_main.h"
/*
* RAIL_PDU_HEADER
* begin
* orderType = 2 bytes
* orderLength = 2 bytes
end
*/
static size_t RAIL_PDU_HEADER_SIZE = 4;
void stream_init_by_allocated_data(STREAM* s, void* data, size_t size)
{
s->data = data;
s->size = size;
s->p = s->data;
}
void* rail_alloc_order_data(size_t length)
{
uint8 * order_start = xmalloc(length + RAIL_PDU_HEADER_SIZE);
return (order_start + RAIL_PDU_HEADER_SIZE);
}
// Used by 'rail_vchannel_send_' routines for sending constructed RAIL PDU to
// the 'rail' channel
static void rail_vchannel_send_order_data(RAIL_SESSION* session, uint16 order_type, void* allocated_order_data, uint16 data_length)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
uint8* header_start = ((uint8*)allocated_order_data - RAIL_PDU_HEADER_SIZE);
data_length += RAIL_PDU_HEADER_SIZE;
stream_init_by_allocated_data(s, header_start, RAIL_PDU_HEADER_SIZE);
stream_write_uint16(s, order_type);
stream_write_uint16(s, data_length);
session->data_sender->send_rail_vchannel_data(
session->data_sender->data_sender_object,
header_start, data_length);
// In there we free memory which we allocated in rail_alloc_order_data(..)
xfree(header_start);
}
/*
* The Handshake PDU is exchanged between the server and the client to
* establish that both endpoints are ready to begin RAIL mode.
* The server sends the Handshake PDU and the client responds
* with the Handshake PDU.
*/
void rail_vchannel_send_handshake_order(RAIL_SESSION * session, uint32 build_number)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
uint16 data_length = 4;
void* data = rail_alloc_order_data(data_length);
DEBUG_RAIL("Send Handshake Order");
stream_init_by_allocated_data(s, data, data_length);
stream_write_uint32(s, build_number);
rail_vchannel_send_order_data(session, RDP_RAIL_ORDER_HANDSHAKE, data, data_length);
}
/*
* The Client Activate PDU is sent from client to server
* when a local RAIL window on the client is activated or deactivated.
*/
void rail_vchannel_send_activate_order(RAIL_SESSION* session, uint32 window_id, uint8 enabled)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
uint16 data_length = 5;
void* data = rail_alloc_order_data(data_length);
stream_init_by_allocated_data(s, data, data_length);
stream_write_uint32(s, window_id);
stream_write_uint8(s, enabled);
rail_vchannel_send_order_data(session, RDP_RAIL_ORDER_ACTIVATE, data, data_length);
}
/*
* Indicates a Client Execute PDU from client to server to request that a
* remote application launch on the server.
* */
void rail_vchannel_send_exec_order(RAIL_SESSION* session, uint16 flags,
UNICODE_STRING* exe_or_file, UNICODE_STRING* working_directory, UNICODE_STRING* arguments)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
uint16 exe_or_file_length = exe_or_file->length;
uint16 working_directory_length = working_directory->length;
uint16 arguments_length = arguments->length;
size_t data_length =
2 + /*Flags (2 bytes)*/
2 + /*ExeOrFileLength (2 bytes)*/
2 + /*WorkingDirLength (2 bytes)*/
2 + /*ArgumentsLen (2 bytes)*/
exe_or_file_length + /*ExeOrFile (variable)*/
working_directory_length + /*WorkingDir (variable)*/
arguments_length; /*Arguments (variable):*/
void* data = rail_alloc_order_data(data_length);
stream_init_by_allocated_data(s, data, data_length);
stream_write_uint16(s, flags);
stream_write_uint16(s, exe_or_file_length);
stream_write_uint16(s, working_directory_length);
stream_write_uint16(s, arguments_length);
rail_write_unicode_string_value(s, exe_or_file);
rail_write_unicode_string_value(s, working_directory);
rail_write_unicode_string_value(s, arguments);
rail_vchannel_send_order_data(session, RDP_RAIL_ORDER_EXEC, data, data_length);
}
size_t get_sysparam_size_in_rdp_stream(RAIL_CLIENT_SYSPARAM * sysparam)
{
switch (sysparam->type)
{
case SPI_SET_DRAG_FULL_WINDOWS: {return 1;}
case SPI_SET_KEYBOARD_CUES: {return 1;}
case SPI_SET_KEYBOARD_PREF: {return 1;}
case SPI_SET_MOUSE_BUTTON_SWAP: {return 1;}
case SPI_SET_WORK_AREA: {return 8;}
case SPI_DISPLAY_CHANGE: {return 8;}
case SPI_TASKBAR_POS: {return 8;}
case SPI_SET_HIGH_CONTRAST:
{
return (4 + /*Flags (4 bytes)*/
4 + /*ColorSchemeLength (4 bytes)*/
2 + /*UNICODE_STRING.cbString (2 bytes)*/
sysparam->value.high_contrast_system_info.color_scheme.length);
}
};
assert(!"Unknown sysparam type");
return 0;
}
/*
* Indicates a Client System Parameters Update PDU from client to server to
* synchronize system parameters on the server with those on the client.
*/
void rail_vchannel_send_client_sysparam_update_order(RAIL_SESSION* session, RAIL_CLIENT_SYSPARAM* sysparam)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
size_t data_length = 4; /*SystemParam (4 bytes)*/
void* data = 0;
data_length += get_sysparam_size_in_rdp_stream(sysparam);
data = rail_alloc_order_data(data_length);
stream_init_by_allocated_data(s, data, data_length);
stream_write_uint32(s, sysparam->type);
switch (sysparam->type)
{
case SPI_SET_DRAG_FULL_WINDOWS:
stream_write_uint8(s, sysparam->value.full_window_drag_enabled);
break;
case SPI_SET_KEYBOARD_CUES:
stream_write_uint8(s, sysparam->value.menu_access_key_always_underlined);
break;
case SPI_SET_KEYBOARD_PREF:
stream_write_uint8(s, sysparam->value.keyboard_for_user_prefered);
break;
case SPI_SET_MOUSE_BUTTON_SWAP:
stream_write_uint8(s, sysparam->value.left_right_mouse_buttons_swapped);
break;
case SPI_SET_WORK_AREA:
rail_write_rectangle_16(s, &sysparam->value.work_area);
break;
case SPI_DISPLAY_CHANGE:
rail_write_rectangle_16(s, &sysparam->value.display_resolution);
break;
case SPI_TASKBAR_POS:
rail_write_rectangle_16(s, &sysparam->value.taskbar_size);
break;
case SPI_SET_HIGH_CONTRAST:
{
uint32 color_scheme_length = 2 +
sysparam->value.high_contrast_system_info.color_scheme.length;
stream_write_uint32(s, sysparam->value.high_contrast_system_info.flags);
stream_write_uint32(s, color_scheme_length);
rail_write_unicode_string_value(s, &sysparam->value.high_contrast_system_info.color_scheme);
break;
}
default:
assert(!"Unknown sysparam type");
break;
}
rail_vchannel_send_order_data(session, RDP_RAIL_ORDER_SYSPARAM, data, data_length);
}
/*
* Indicates a Client System Command PDU from client to server when a local
* RAIL window on the client receives a command to perform an action on the
* window, such as minimize or maximize.
*/
void rail_vchannel_send_syscommand_order(RAIL_SESSION* session, uint32 window_id, uint16 command)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
uint16 data_length = 4 + 2;
void* data = rail_alloc_order_data(data_length);
stream_init_by_allocated_data(s, data, data_length);
stream_write_uint32(s, window_id);
stream_write_uint16(s, command);
rail_vchannel_send_order_data(session, RDP_RAIL_ORDER_SYSCOMMAND, data, data_length);
}
/*
* The Client Notify Event PDU packet is sent from a client to a server when
* a local RAIL Notification Icon on the client receives a keyboard or mouse
* message from the user. This notification is forwarded to the server via
* the Notify Event PDU.
* */
void rail_vchannel_send_notify_event_order(RAIL_SESSION * session, uint32 window_id, uint32 notify_icon_id, uint32 message)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
uint16 data_length = 4 * 3;
void* data = rail_alloc_order_data(data_length);
stream_init_by_allocated_data(s, data, data_length);
stream_write_uint32(s, window_id);
stream_write_uint32(s, notify_icon_id);
stream_write_uint32(s, message);
rail_vchannel_send_order_data(session, RDP_RAIL_ORDER_NOTIFY_EVENT, data, data_length);
}
/*
* The Client Window Move PDU packet is sent from the client to the server
* when a local window is ending a move or resize. The client communicates the
* locally moved or resized window's position to the server by using this packet.
* The server uses this information to reposition its window.*/
void rail_vchannel_send_client_windowmove_order(RAIL_SESSION* session, uint32 window_id, RECTANGLE_16* new_position)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
uint16 data_length = 4 + 2 * 4;
void* data = rail_alloc_order_data(data_length);
stream_init_by_allocated_data(s, data, data_length);
stream_write_uint32(s, window_id);
stream_write_uint16(s, new_position->left);
stream_write_uint16(s, new_position->top);
stream_write_uint16(s, new_position->right);
stream_write_uint16(s, new_position->bottom);
rail_vchannel_send_order_data(session, RDP_RAIL_ORDER_WINDOWMOVE, data, data_length);
}
/*
* The Client Information PDU is sent from client to server and contains
* information about RAIL client state and features supported by the client.
* */
void rail_vchannel_send_client_information_order(RAIL_SESSION* session, uint32 flags)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
uint16 data_length = 4;
void* data = rail_alloc_order_data(data_length);
DEBUG_RAIL("Send Client Information Order");
stream_init_by_allocated_data(s, data, data_length);
stream_write_uint32(s, flags);
rail_vchannel_send_order_data(session, RDP_RAIL_ORDER_CLIENTSTATUS, data, data_length);
}
/*
* The Client System Menu PDU packet is sent from the client to the server
* when a local RAIL window on the client receives a command to display its
* System menu. This command is forwarded to the server via
* the System menu PDU.
*/
void rail_vchannel_send_client_system_menu_order(RAIL_SESSION* session, uint32 window_id, uint16 left, uint16 top)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
uint16 data_length = 4 + 2 * 2;
void* data = rail_alloc_order_data(data_length);
stream_init_by_allocated_data(s, data, data_length);
stream_write_uint32(s, window_id);
stream_write_uint16(s, left);
stream_write_uint16(s, top);
rail_vchannel_send_order_data(session, RDP_RAIL_ORDER_SYSMENU, data, data_length);
}
/*
* The Language Bar Information PDU is used to set the language bar status.
* It is sent from a client to a server or a server to a client, but only when
* both support the Language Bar docking capability
* (TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED).
* This PDU contains information about the language bar status.
* */
void rail_vchannel_send_client_langbar_information_order(RAIL_SESSION* session, uint32 langbar_status)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
uint16 data_length = 4;
void* data = rail_alloc_order_data(data_length);
stream_init_by_allocated_data(s, data, data_length);
stream_write_uint32(s, langbar_status);
rail_vchannel_send_order_data(session, RDP_RAIL_ORDER_LANGBARINFO, data, data_length);
}
/*
* The Client Get Application ID PDU is sent from a client to a server.
* This PDU requests information from the server about the Application ID
* that the window SHOULD <15> have on the client.
* */
void rail_vchannel_send_get_appid_req_order(RAIL_SESSION* session, uint32 window_id)
{
STREAM st_stream = {0};
STREAM* s = &st_stream;
uint16 data_length = 4;
void* data = rail_alloc_order_data(data_length);
stream_init_by_allocated_data(s, data, data_length);
stream_write_uint32(s, window_id);
rail_vchannel_send_order_data(session, RDP_RAIL_ORDER_GET_APPID_REQ, data, data_length);
}
/*
* Look at rail_vchannel_send_handshake_order(...)
*/
void rail_vchannel_process_handshake_order(RAIL_SESSION* session, STREAM* s)
{
uint32 build_number = 0;
stream_read_uint32(s, build_number);
rail_core_handle_server_handshake(session, build_number);
}
/*
* The Server Execute Result PDU is sent from server to client in response to
* a Client Execute PDU request, and contains the result of the server's
* attempt to launch the requested executable.
*/
void rail_vchannel_process_exec_result_order(RAIL_SESSION* session, STREAM* s)
{
uint16 flags = 0;
uint16 exec_result = 0;
uint32 raw_result = 0;
UNICODE_STRING exe_or_file = {0};
stream_read_uint16(s, flags); /*Flags (2 bytes)*/
stream_read_uint16(s, exec_result); /*ExecResult (2 bytes)*/
stream_read_uint32(s, raw_result); /*RawResult (4 bytes)*/
stream_seek(s, 2); /*Padding (2 bytes)*/
rail_read_unicode_string(s, &exe_or_file); /*ExeOrFileLength with ExeOrFile (variable)*/
rail_core_handle_exec_result(session, flags, exec_result, raw_result, &exe_or_file);
rail_unicode_string_free(&exe_or_file);
}
/*
* The Server System Parameters Update PDU is sent from the server to client to
* synchronize system parameters on the client with those on the server.
*/
void rail_vchannel_process_server_sysparam_update_order(RAIL_SESSION* session, STREAM* s)
{
RAIL_SERVER_SYSPARAM sysparam = {0};
stream_read_uint32(s, sysparam.type);
switch (sysparam.type)
{
case SPI_SET_SCREEN_SAVE_ACTIVE:
stream_read_uint8(s, sysparam.value.screen_saver_enabled);
break;
case SPI_SET_SCREEN_SAVE_SECURE:
stream_read_uint8(s, sysparam.value.screen_saver_lock_enabled);
break;
default:
assert(!"Undocumented RAIL server sysparam type");
break;
};
rail_core_handle_server_sysparam(session, &sysparam);
}
/*
* The Server Move/Size Start PDU packet is sent by the server when a window on
* the server is beginning a move or resize.
* The client uses this information to initiate a local move or resize of the
* corresponding local window.
*
* The Server Move/Size End PDU is sent by the server when a window on the
* server is completing a move or resize.
* The client uses this information to end a local move/resize of the
* corresponding local window.
*
*/
void rail_vchannel_process_server_movesize_order(RAIL_SESSION* session, STREAM* s)
{
uint32 window_id = 0;
uint16 move_size_started = 0;
uint16 move_size_type = 0;
uint16 pos_x = 0;
uint16 pos_y = 0;
stream_read_uint32(s, window_id);
stream_read_uint16(s, move_size_started);
stream_read_uint16(s, move_size_type);
stream_read_uint16(s, pos_x);
stream_read_uint16(s, pos_y);
rail_core_handle_server_movesize(session, window_id, move_size_started, move_size_type, pos_x, pos_y);
}
/*
* The Server Min Max Info PDU is sent from a server to a client when a window
* move or resize on the server is being initiated.
* This PDU contains information about the minimum and maximum extents to
* which the window can be moved or sized.
*/
void rail_vchannel_process_server_minmax_info_order(RAIL_SESSION* session, STREAM* s)
{
uint32 window_id = 0;
uint16 max_width = 0;
uint16 max_height = 0;
uint16 max_pos_x = 0;
uint16 max_pos_y = 0;
uint16 min_track_width = 0;
uint16 min_track_height = 0;
uint16 max_track_width = 0;
uint16 max_track_height = 0;
stream_read_uint32(s, window_id);
stream_read_uint16(s, max_width);
stream_read_uint16(s, max_height);
stream_read_uint16(s, max_pos_x);
stream_read_uint16(s, max_pos_y);
stream_read_uint16(s, min_track_width);
stream_read_uint16(s, min_track_height);
stream_read_uint16(s, max_track_width);
stream_read_uint16(s, max_track_height);
rail_core_handle_server_minmax_info(session, window_id, max_width,
max_height, max_pos_x, max_pos_y, min_track_width, min_track_height,
max_track_width, max_track_height);
}
/*
*The Language Bar Information PDU is used to set the language bar status.
*/
void rail_vchannel_process_server_langbar_info_order(RAIL_SESSION* session, STREAM* s)
{
uint32 langbar_status = 0;
stream_read_uint32(s, langbar_status);
rail_core_handle_server_langbar_info(session, langbar_status);
}
/*
* The Server Get Application ID Response PDU is sent from a server to a client.
* This PDU MAY be sent to the client as a response to a Client Get Application
* ID PDU. This PDU specifies the Application ID that the specified window
* SHOULD have on the client. The client MAY ignore this PDU.
*/
static void rail_vchannel_process_server_get_appid_resp_order(RAIL_SESSION* session, STREAM* s)
{
uint32 window_id = 0;
UNICODE_STRING app_id = {0};
app_id.length = 256;
app_id.string = xmalloc(app_id.length);
stream_read_uint32(s, window_id);
stream_read(s, app_id.string, app_id.length);
rail_core_handle_server_get_app_resp(session, window_id, &app_id);
rail_unicode_string_free(&app_id);
}
extern uint8 RAIL_ORDER_TYPE_STRINGS[][32];
void rail_vchannel_process_received_vchannel_data(RAIL_SESSION * session, STREAM* s)
{
size_t length = 0;
uint16 order_type = 0;
uint16 order_length = 0;
length = ((s->data + s->size) - s->p);
stream_read_uint16(s, order_type); /* orderType */
stream_read_uint16(s, order_length); /* orderLength */
DEBUG_RAIL("rail_on_channel_data_received: session=0x%p data_size=%d "
"orderType=0x%X orderLength=%d", session, (int) length, order_type, order_length);
printf("Received %s PDU, length:%d\n",
RAIL_ORDER_TYPE_STRINGS[((order_type & 0xF0) >> 3) + (order_type & 0x0F)], order_length);
switch (order_type)
{
case RDP_RAIL_ORDER_HANDSHAKE:
rail_vchannel_process_handshake_order(session, s);
break;
case RDP_RAIL_ORDER_EXEC_RESULT:
rail_vchannel_process_exec_result_order(session, s);
break;
case RDP_RAIL_ORDER_SYSPARAM:
rail_vchannel_process_server_sysparam_update_order(session, s);
break;
case RDP_RAIL_ORDER_LOCALMOVESIZE:
rail_vchannel_process_server_movesize_order(session, s);
break;
case RDP_RAIL_ORDER_MINMAXINFO:
rail_vchannel_process_server_minmax_info_order(session, s);
break;
case RDP_RAIL_ORDER_LANGBARINFO:
rail_vchannel_process_server_langbar_info_order(session, s);
break;
case RDP_RAIL_ORDER_GET_APPID_RESP:
rail_vchannel_process_server_get_appid_resp_order(session, s);
break;
default:
DEBUG_RAIL("rail_on_channel_data_received: "
"Undocumented RAIL server PDU: order_type=0x%X",order_type);
break;
}
}

View File

@ -1,40 +0,0 @@
/*
FreeRDP: A Remote Desktop Protocol client.
Remote Applications Integrated Locally (RAIL)
Copyright 2009 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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.
*/
#ifndef __RAIL_CHANNEL_ORDERS_H
#define __RAIL_CHANNEL_ORDERS_H
#include "rail_core.h"
void rail_vchannel_send_handshake_order(RAIL_SESSION* session, uint32 build_number);
void rail_vchannel_send_client_information_order(RAIL_SESSION* session, uint32 flags);
void rail_vchannel_send_activate_order(RAIL_SESSION* session, uint32 window_id, uint8 enabled);
void rail_vchannel_send_exec_order(RAIL_SESSION* session, uint16 flags, UNICODE_STRING* exe_or_file,
UNICODE_STRING* working_directory, UNICODE_STRING* arguments);
void rail_vchannel_send_client_sysparam_update_order(RAIL_SESSION* session, RAIL_CLIENT_SYSPARAM* sysparam);
void rail_vchannel_send_syscommand_order(RAIL_SESSION* session, uint32 window_id, uint16 command);
void rail_vchannel_send_notify_event_order(RAIL_SESSION* session, uint32 window_id, uint32 notify_icon_id, uint32 message);
void rail_vchannel_send_client_windowmove_order(RAIL_SESSION* session, uint32 window_id, RECTANGLE_16* new_position);
void rail_vchannel_send_client_system_menu_order(RAIL_SESSION* session, uint32 window_id, uint16 left, uint16 top);
void rail_vchannel_send_client_langbar_information_order(RAIL_SESSION* session, uint32 langbar_status);
void rail_vchannel_send_get_appid_req_order(RAIL_SESSION* session, uint32 window_id);
void rail_vchannel_process_received_vchannel_data(RAIL_SESSION* session, STREAM* s);
#endif /* __RAIL_CHANNEL_ORDERS_H */

View File

@ -1,570 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* Remote Applications Integrated Locally (RAIL)
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* 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 <stdlib.h>
#include <string.h>
#include <freerdp/constants.h>
#include <freerdp/types.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/hexdump.h>
#include <freerdp/utils/unicode.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/utils/rail.h>
#include <freerdp/rail.h>
#include "rail_core.h"
#include "rail_channel_orders.h"
/*
// Initialization stage in UI for RAIL:
// 1) create a sequence of rail_notify_client_sysparam_update()
// calls with all current client system parameters
//
// 2) if Language Bar capability enabled - call updating Language Bar PDU
//
// 3) prepare and call rail_client_execute(exe_or_file, working_dir, args)
//
*/
/*
Flow of init stage over channel;
Client notify UI about session start
and go to RAIL_ESTABLISHING state.
Client wait for Server Handshake PDU
Server send Handshake request
Client check Handshake response.
If NOT OK - exit with specified reason
Client send Handshake response
Server send Server System
Parameters Update (in parallel)
Client send Client Information
Client send Client System Parameters Update
Client send Client Execute
Server send Server Execute Result
Client check Server Execute Result. If NOT OK - exit with specified reason
Client notify UI about success session establishing and go to
RAIL_ESTABLISHED state.
*/
void init_vchannel_event(RAIL_VCHANNEL_EVENT* event, uint32 event_id)
{
memset(event, 0, sizeof(RAIL_VCHANNEL_EVENT));
event->event_id = event_id;
}
void init_rail_string(RAIL_STRING * rail_string, const char * string)
{
rail_string->buffer = (uint8*)string;
rail_string->length = strlen(string) + 1;
}
void rail_string_to_unicode_string(rdpRail* rail, char* string, UNICODE_STRING* unicode_string)
{
char* buffer;
size_t length = 0;
unicode_string->string = NULL;
unicode_string->length = 0;
if (strlen(string) < 1)
return;
buffer = freerdp_uniconv_out(rail->uniconv, string, &length);
unicode_string->string = (uint8*) buffer;
unicode_string->length = (uint16) length;
}
void rail_string2unicode_string(RAIL_SESSION* session, RAIL_STRING* string, UNICODE_STRING* unicode_string)
{
size_t result_length = 0;
char* result_buffer = NULL;
unicode_string->string = NULL;
unicode_string->length = 0;
if (string->length == 0) return;
result_buffer = freerdp_uniconv_out(session->uniconv, (char*) string->buffer, &result_length);
unicode_string->string = (uint8*) result_buffer;
unicode_string->length = (uint16) result_length;
}
void rail_unicode_string2string(RAIL_SESSION* session, UNICODE_STRING* unicode_string, RAIL_STRING* string)
{
char* result_buffer = NULL;
string->buffer = NULL;
string->length = 0;
if (unicode_string->length == 0)
return;
result_buffer = freerdp_uniconv_in(session->uniconv, unicode_string->string, unicode_string->length);
string->buffer = (uint8*)result_buffer;
string->length = strlen(result_buffer) + 1;
}
RAIL_SESSION* rail_core_session_new(RAIL_VCHANNEL_DATA_SENDER* data_sender, RAIL_VCHANNEL_EVENT_SENDER* event_sender)
{
RAIL_SESSION* self;
self = (RAIL_SESSION*) xzalloc(sizeof(RAIL_SESSION));
if (self != NULL)
{
self->data_sender = data_sender;
self->event_sender = event_sender;
self->uniconv = freerdp_uniconv_new();
self->rail = rail_new();
self->rail->data_sender = data_sender;
self->rail->event_sender = event_sender;
}
return self;
}
void rail_core_session_free(RAIL_SESSION* rail_session)
{
if (rail_session != NULL)
{
rail_free(rail_session->rail);
freerdp_uniconv_free(rail_session->uniconv);
xfree(rail_session);
}
}
void rail_core_on_channel_connected(RAIL_SESSION* session)
{
DEBUG_RAIL("RAIL channel connected.");
}
void rail_core_on_channel_terminated(RAIL_SESSION* session)
{
DEBUG_RAIL("RAIL channel terminated.");
}
void rail_core_handle_server_handshake(RAIL_SESSION* session, uint32 build_number)
{
#if 1
DEBUG_RAIL("Server Handshake");
session->rail->handshake.buildNumber = 0x00001DB1;
rail_send_handshake_order(session->rail);
session->rail->client_status.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE;
rail_send_client_status_order(session->rail);
/* sysparam update */
session->rail->sysparam.systemParam = SPI_SET_HIGH_CONTRAST;
session->rail->sysparam.highContrast.colorScheme.string = NULL;
session->rail->sysparam.highContrast.colorScheme.length = 0;
session->rail->sysparam.highContrast.flags = 0x7E;
rail_send_client_sysparam_order(session->rail);
session->rail->sysparam.systemParam = SPI_TASKBAR_POS;
session->rail->sysparam.rectangle.left = 0;
session->rail->sysparam.rectangle.top = 0;
session->rail->sysparam.rectangle.right = 1024;
session->rail->sysparam.rectangle.bottom = 29;
rail_send_client_sysparam_order(session->rail);
session->rail->sysparam.systemParam = SPI_SET_MOUSE_BUTTON_SWAP;
session->rail->sysparam.value = False;
rail_send_client_sysparam_order(session->rail);
session->rail->sysparam.systemParam = SPI_SET_KEYBOARD_PREF;
session->rail->sysparam.value = False;
rail_send_client_sysparam_order(session->rail);
session->rail->sysparam.systemParam = SPI_SET_DRAG_FULL_WINDOWS;
session->rail->sysparam.value = True;
rail_send_client_sysparam_order(session->rail);
session->rail->sysparam.systemParam = SPI_SET_KEYBOARD_CUES;
session->rail->sysparam.value = False;
rail_send_client_sysparam_order(session->rail);
session->rail->sysparam.systemParam = SPI_SET_WORK_AREA;
session->rail->sysparam.rectangle.left = 0;
session->rail->sysparam.rectangle.top = 0;
session->rail->sysparam.rectangle.right = 1024;
session->rail->sysparam.rectangle.bottom = 768;
rail_send_client_sysparam_order(session->rail);
/* execute */
session->rail->exec.flags =
RAIL_EXEC_FLAG_EXPAND_WORKINGDIRECTORY |
RAIL_EXEC_FLAG_EXPAND_ARGUMENTS;
rail_string_to_unicode_string(session->rail, "||firefox", &session->rail->exec.exeOrFile);
rail_string_to_unicode_string(session->rail, "", &session->rail->exec.workingDir);
rail_string_to_unicode_string(session->rail, "", &session->rail->exec.arguments);
//rail_send_client_exec_order(session->rail);
rail_core_send_client_execute(session, False, "||firefox", "", "");
#else
uint32 client_build_number = 0x00001db0;
RAIL_VCHANNEL_EVENT event = {0};
DEBUG_RAIL("rail_core_handle_server_handshake: session=0x%p buildNumber=0x%X.", session, build_number);
// Step 1. Send Handshake PDU (2.2.2.2.1)
// Fixed: MS-RDPERP 1.3.2.1 is not correct!
rail_vchannel_send_handshake_order(session, client_build_number);
// Step 2. Send Client Information PDU (2.2.2.2.1)
rail_vchannel_send_client_information_order(session, RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE);
// Step 3. Notify UI about session establishing and about requirements to
// start UI initialization stage.
init_vchannel_event(&event, RAIL_VCHANNEL_EVENT_SESSION_ESTABLISHED);
session->event_sender->send_rail_vchannel_event(session->event_sender->event_sender_object, &event);
// Step 4. Send Client Execute
// FIXME:
// According to "3.1.1.1 Server State Machine" Client Execute
// will be processed after Destop Sync processed.
// So maybe send after receive Destop Sync sequence?
rail_core_send_client_execute(session, False, "||firefox", "", "");
#endif
}
void rail_core_handle_exec_result(RAIL_SESSION* session, uint16 flags, uint16 exec_result, uint32 raw_result, UNICODE_STRING* exe_or_file)
{
DEBUG_RAIL("EXEC_RESULT");
#if 0
RAIL_VCHANNEL_EVENT event = {0};
RAIL_STRING exe_or_file_;
DEBUG_RAIL("rail_core_handle_exec_result: session=0x%p flags=0x%X "
"exec_result=0x%X raw_result=0x%X exe_or_file=(length=%d dump>)",
session, flags, exec_result, raw_result, exe_or_file->length);
#ifdef WITH_DEBUG_RAIL
freerdp_hexdump(exe_or_file->string, exe_or_file->length);
#endif
rail_unicode_string2string(session, exe_or_file, &exe_or_file_);
init_vchannel_event(&event, RAIL_VCHANNEL_EVENT_EXEC_RESULT_RETURNED);
event.param.exec_result_info.flags = flags;
event.param.exec_result_info.exec_result = exec_result;
event.param.exec_result_info.raw_result = raw_result;
event.param.exec_result_info.exe_or_file = exe_or_file_.buffer;
session->event_sender->send_rail_vchannel_event(session->event_sender->event_sender_object, &event);
#endif
}
void rail_core_handle_server_sysparam(RAIL_SESSION* session, RAIL_SERVER_SYSPARAM* sysparam)
{
#if 0
RAIL_VCHANNEL_EVENT event = {0};
DEBUG_RAIL("rail_core_handle_server_sysparam: session=0x%p "
"type=0x%X scr_enabled=%d scr_lock_enabled=%d",
session, sysparam->type, sysparam->value.screen_saver_enabled,
sysparam->value.screen_saver_lock_enabled);
init_vchannel_event(&event, RAIL_VCHANNEL_EVENT_SERVER_SYSPARAM_RECEIVED);
event.param.server_param_info.param_type = sysparam->type;
event.param.server_param_info.screen_saver_enabled =
((sysparam->value.screen_saver_enabled != 0) ? True: False);
event.param.server_param_info.screen_saver_lock_enabled =
((sysparam->value.screen_saver_lock_enabled != 0) ? True: False);
session->event_sender->send_rail_vchannel_event(session->event_sender->event_sender_object, &event);
#endif
}
void rail_core_handle_server_movesize(RAIL_SESSION* session, uint32 window_id,
uint16 move_size_started, uint16 move_size_type, uint16 pos_x, uint16 pos_y)
{
RAIL_VCHANNEL_EVENT event = {0};
DEBUG_RAIL("rail_core_handle_server_movesize: session=0x%p "
"window_id=0x%X started=%d move_size_type=%d pos_x=%d pos_y=%d",
session, window_id, move_size_started, move_size_type, pos_x, pos_y);
init_vchannel_event(&event, ((move_size_started != 0) ?
RAIL_VCHANNEL_EVENT_MOVESIZE_STARTED:
RAIL_VCHANNEL_EVENT_MOVESIZE_FINISHED));
event.param.movesize_info.window_id = window_id;
event.param.movesize_info.move_size_type = move_size_type;
event.param.movesize_info.pos_x = pos_x;
event.param.movesize_info.pos_y = pos_y;
session->event_sender->send_rail_vchannel_event(session->event_sender->event_sender_object, &event);
}
void rail_core_handle_server_minmax_info(RAIL_SESSION* session,
uint32 window_id, uint16 max_width, uint16 max_height, uint16 max_pos_x, uint16 max_pos_y,
uint16 min_track_width, uint16 min_track_height, uint16 max_track_width, uint16 max_track_height)
{
RAIL_VCHANNEL_EVENT event = {0};
DEBUG_RAIL("rail_core_handle_server_minmax_info: session=0x%p "
"window_id=0x%X max_width=%d max_height=%d max_pos_x=%d max_pos_y=%d "
"min_track_width=%d min_track_height=%d max_track_width=%d max_track_height=%d",
session, window_id, max_width, max_height, max_pos_x, max_pos_y,
min_track_width, min_track_height, max_track_width, max_track_height);
init_vchannel_event(&event, RAIL_VCHANNEL_EVENT_MINMAX_INFO_UPDATED);
event.param.minmax_info.window_id = window_id;
event.param.minmax_info.max_width = max_width;
event.param.minmax_info.max_height = max_height;
event.param.minmax_info.max_pos_x = max_pos_x;
event.param.minmax_info.max_pos_y = max_pos_y;
event.param.minmax_info.min_track_width = min_track_width;
event.param.minmax_info.min_track_height = min_track_height;
event.param.minmax_info.max_track_width = max_track_width;
event.param.minmax_info.max_track_height = max_track_height;
session->event_sender->send_rail_vchannel_event(session->event_sender->event_sender_object, &event);
}
void rail_core_handle_server_langbar_info(RAIL_SESSION* session, uint32 langbar_status)
{
RAIL_VCHANNEL_EVENT event = {0};
DEBUG_RAIL("rail_core_handle_server_langbar_info: session=0x%p "
"langbar_status=0x%X", session, langbar_status);
init_vchannel_event(&event, RAIL_VCHANNEL_EVENT_LANGBAR_STATUS_UPDATED);
event.param.langbar_info.status = langbar_status;
session->event_sender->send_rail_vchannel_event(session->event_sender->event_sender_object, &event);
}
void rail_core_handle_server_get_app_resp(RAIL_SESSION* session, uint32 window_id, UNICODE_STRING * app_id)
{
RAIL_VCHANNEL_EVENT event = { 0 };
RAIL_STRING app_id_;
DEBUG_RAIL("rail_core_handle_server_get_app_resp: session=0x%p "
"window_id=0x%X app_id=(length=%d dump>)", session, window_id, app_id->length);
#ifdef WITH_DEBUG_RAIL
freerdp_hexdump(app_id->string, app_id->length);
#endif
rail_unicode_string2string(session, app_id, &app_id_);
init_vchannel_event(&event, RAIL_VCHANNEL_EVENT_LANGBAR_STATUS_UPDATED);
event.param.app_response_info.window_id= window_id;
event.param.app_response_info.application_id = app_id_.buffer;
session->event_sender->send_rail_vchannel_event(session->event_sender->event_sender_object, &event);
}
void rail_core_send_client_execute(RAIL_SESSION* session,
boolean exec_or_file_is_file_path, const char* rail_exe_or_file,
const char* rail_working_directory, const char* rail_arguments)
{
RAIL_STRING exe_or_file_;
RAIL_STRING working_directory_;
RAIL_STRING arguments_;
UNICODE_STRING exe_or_file;
UNICODE_STRING working_directory;
UNICODE_STRING arguments;
uint16 flags;
init_rail_string(&exe_or_file_, rail_exe_or_file);
init_rail_string(&working_directory_, rail_working_directory);
init_rail_string(&arguments_, rail_arguments);
rail_string2unicode_string(session, &exe_or_file_, &exe_or_file);
rail_string2unicode_string(session, &working_directory_, &working_directory);
rail_string2unicode_string(session, &arguments_, &arguments);
flags = (RAIL_EXEC_FLAG_EXPAND_WORKINGDIRECTORY | RAIL_EXEC_FLAG_EXPAND_ARGUMENTS);
if (exec_or_file_is_file_path)
{
flags |= (RAIL_EXEC_FLAG_TRANSLATE_FILES | RAIL_EXEC_FLAG_FILE);
}
rail_vchannel_send_exec_order(session, flags, &exe_or_file,
&working_directory, &arguments);
rail_unicode_string_free(&exe_or_file);
rail_unicode_string_free(&working_directory);
rail_unicode_string_free(&arguments);
}
uint8 boolean2uint8(boolean value)
{
return ((value == True) ? 1 : 0);
}
uint8 copy_rail_rect_16(RECTANGLE_16* src, RECTANGLE_16* dst)
{
memcpy(dst, src, sizeof(RECTANGLE_16));
return 0;
}
void rail_core_handle_ui_update_client_sysparam(RAIL_SESSION* session, RAIL_UI_EVENT* event)
{
RAIL_CLIENT_SYSPARAM sys_param;
memset(&sys_param, 0, sizeof(sys_param));
sys_param.type = event->param.sysparam_info.param;
sys_param.value.full_window_drag_enabled =
boolean2uint8(event->param.sysparam_info.value.full_window_drag_enabled);
sys_param.value.menu_access_key_always_underlined =
boolean2uint8(event->param.sysparam_info.value.menu_access_key_always_underlined);
sys_param.value.keyboard_for_user_prefered =
boolean2uint8(event->param.sysparam_info.value.keyboard_for_user_prefered);
sys_param.value.left_right_mouse_buttons_swapped =
boolean2uint8(event->param.sysparam_info.value.left_right_mouse_buttons_swapped);
copy_rail_rect_16(&event->param.sysparam_info.value.work_area,
&sys_param.value.work_area);
copy_rail_rect_16(&event->param.sysparam_info.value.display_resolution,
&sys_param.value.display_resolution);
copy_rail_rect_16(&event->param.sysparam_info.value.taskbar_size,
&sys_param.value.taskbar_size);
sys_param.value.high_contrast_system_info.flags =
event->param.sysparam_info.value.high_contrast_system_info.flags;
if (sys_param.type == SPI_SET_HIGH_CONTRAST)
{
RAIL_STRING color_scheme;
init_rail_string(&color_scheme,
event->param.sysparam_info.value.high_contrast_system_info.color_scheme);
rail_string2unicode_string(session, &color_scheme, &sys_param.value.high_contrast_system_info.color_scheme);
}
rail_vchannel_send_client_sysparam_update_order(session, &sys_param);
rail_unicode_string_free(&sys_param.value.high_contrast_system_info.color_scheme);
}
static void rail_core_handle_ui_execute_remote_app(RAIL_SESSION* session, RAIL_UI_EVENT* event)
{
rail_core_send_client_execute(session,
event->param.execute_info.exec_or_file_is_file_path,
event->param.execute_info.exe_or_file,
event->param.execute_info.working_directory,
event->param.execute_info.arguments);
}
static void rail_core_handle_ui_activate(RAIL_SESSION* session, RAIL_UI_EVENT* event)
{
rail_vchannel_send_activate_order(
session, event->param.activate_info.window_id,
((event->param.activate_info.enabled == True) ? 1 : 0));
}
static void rail_core_handle_ui_sys_command(RAIL_SESSION* session, RAIL_UI_EVENT* event)
{
rail_vchannel_send_syscommand_order(session,
event->param.syscommand_info.window_id,
event->param.syscommand_info.syscommand);
}
static void rail_core_handle_ui_notify(RAIL_SESSION* session, RAIL_UI_EVENT* event)
{
rail_vchannel_send_notify_event_order(session,
event->param.notify_info.window_id,
event->param.notify_info.notify_icon_id,
event->param.notify_info.message);
}
static void rail_core_handle_ui_window_move(RAIL_SESSION* session, RAIL_UI_EVENT* event)
{
rail_vchannel_send_client_windowmove_order(session,
event->param.window_move_info.window_id,
&event->param.window_move_info.new_position);
}
static void rail_core_handle_ui_system_menu(RAIL_SESSION* session, RAIL_UI_EVENT* event)
{
rail_vchannel_send_client_system_menu_order(session,
event->param.system_menu_info.window_id,
event->param.system_menu_info.left,
event->param.system_menu_info.top);
}
static void rail_core_handle_ui_get_app_id(RAIL_SESSION* session, RAIL_UI_EVENT* event)
{
rail_vchannel_send_get_appid_req_order(session, event->param.get_app_id_info.window_id);
}
void rail_core_handle_ui_event(RAIL_SESSION* session, RAIL_UI_EVENT* event)
{
return;
struct
{
uint32 event_id;
void (*event_handler)(RAIL_SESSION* session, RAIL_UI_EVENT* event);
} handlers_table[] =
{
{RAIL_UI_EVENT_UPDATE_CLIENT_SYSPARAM, rail_core_handle_ui_update_client_sysparam},
{RAIL_UI_EVENT_EXECUTE_REMOTE_APP, rail_core_handle_ui_execute_remote_app},
{RAIL_UI_EVENT_ACTIVATE, rail_core_handle_ui_activate},
{RAIL_UI_EVENT_SYS_COMMAND, rail_core_handle_ui_sys_command},
{RAIL_UI_EVENT_NOTIFY, rail_core_handle_ui_notify},
{RAIL_UI_EVENT_WINDOW_MOVE, rail_core_handle_ui_window_move},
{RAIL_UI_EVENT_SYSTEM_MENU, rail_core_handle_ui_system_menu},
{RAIL_UI_EVENT_LANGBAR_INFO, rail_core_handle_ui_system_menu},
{RAIL_UI_EVENT_GET_APP_ID, rail_core_handle_ui_get_app_id}
};
int i = 0;
for (i = 0; i < RAIL_ARRAY_SIZE(handlers_table); i++)
{
if ((event->event_id == handlers_table[i].event_id) &&
(handlers_table[i].event_handler != NULL))
{
(handlers_table[i].event_handler)(session, event);
}
}
}

View File

@ -1,147 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* Remote Applications Integrated Locally (RAIL)
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* 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.
*/
#ifndef __RAIL_CORE_H
#define __RAIL_CORE_H
#include <freerdp/types.h>
#include <freerdp/utils/stream.h>
#include <freerdp/utils/unicode.h>
#include <freerdp/rail.h>
#include <assert.h>
#include <freerdp/utils/debug.h>
typedef struct _RAIL_SESSION RAIL_SESSION;
typedef struct _RAIL_VCHANNEL_DATA_SENDER RAIL_VCHANNEL_DATA_SENDER;
typedef struct _RAIL_VCHANNEL_EVENT_SENDER RAIL_VCHANNEL_EVENT_SENDER;
#include "rail_orders.h"
#define WITH_DEBUG_RAIL 1
#ifdef WITH_DEBUG_RAIL
#define DEBUG_RAIL(fmt, ...) DEBUG_CLASS(RAIL, fmt, ## __VA_ARGS__)
#else
#define DEBUG_RAIL(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif
#define RAIL_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
typedef struct _RAIL_STRING
{
uint16 length;
uint8 *buffer;
} RAIL_STRING;
typedef struct _RAIL_HIGHCONTRAST
{
uint32 flags;
UNICODE_STRING color_scheme;
} RAIL_HIGHCONTRAST;
typedef struct _RAIL_CLIENT_SYSPARAM
{
uint32 type;
union
{
uint8 full_window_drag_enabled;
uint8 menu_access_key_always_underlined;
uint8 keyboard_for_user_prefered;
uint8 left_right_mouse_buttons_swapped;
RECTANGLE_16 work_area;
RECTANGLE_16 display_resolution;
RECTANGLE_16 taskbar_size;
RAIL_HIGHCONTRAST high_contrast_system_info;
} value;
} RAIL_CLIENT_SYSPARAM;
struct _RAIL_SERVER_SYSPARAM
{
uint32 type;
union
{
uint8 screen_saver_enabled;
uint8 screen_saver_lock_enabled;
} value;
};
typedef struct _RAIL_SERVER_SYSPARAM RAIL_SERVER_SYSPARAM;
struct _RAIL_VCHANNEL_DATA_SENDER
{
void* data_sender_object;
void (*send_rail_vchannel_data)(void* sender_object, void* data, size_t length);
};
struct _RAIL_VCHANNEL_EVENT_SENDER
{
void * event_sender_object;
void (*send_rail_vchannel_event)(void* ui_event_sender_object, RAIL_VCHANNEL_EVENT* event);
};
struct _RAIL_SESSION
{
rdpRail* rail;
UNICONV* uniconv;
RAIL_VCHANNEL_DATA_SENDER* data_sender;
RAIL_VCHANNEL_EVENT_SENDER* event_sender;
};
RAIL_SESSION* rail_core_session_new(RAIL_VCHANNEL_DATA_SENDER *data_sender, RAIL_VCHANNEL_EVENT_SENDER *event_sender);
void rail_core_session_free(RAIL_SESSION * rail_session);
// RAIL Core Handlers for events from channel plugin interface
void rail_core_on_channel_connected(RAIL_SESSION* rail_session);
void rail_core_on_channel_terminated(RAIL_SESSION* rail_session);
void rail_core_on_channel_data_received(RAIL_SESSION* rail_session, void* data, size_t length);
// RAIL Core Handlers for events from UI
void rail_core_handle_ui_event(RAIL_SESSION* session, RAIL_UI_EVENT* event);
// RAIL Core Handlers for events from channel orders reader
void rail_core_handle_server_handshake(RAIL_SESSION* session, uint32 build_number);
void rail_core_handle_exec_result(RAIL_SESSION* session, uint16 flags,
uint16 exec_result, uint32 raw_result, UNICODE_STRING* exe_or_file);
void rail_core_handle_server_sysparam(RAIL_SESSION* session, RAIL_SERVER_SYSPARAM* sysparam);
void rail_core_handle_server_movesize(RAIL_SESSION* session, uint32 window_id,
uint16 move_size_started, uint16 move_size_type, uint16 pos_x, uint16 pos_y);
void rail_core_handle_server_minmax_info(RAIL_SESSION* session, uint32 window_id,
uint16 max_width, uint16 max_height, uint16 max_pos_x, uint16 max_pos_y,
uint16 min_track_width, uint16 min_track_height, uint16 max_track_width, uint16 max_track_height);
void rail_core_handle_server_langbar_info(RAIL_SESSION* session, uint32 langbar_status);
void rail_core_handle_server_get_app_resp(RAIL_SESSION* session, uint32 window_id, UNICODE_STRING* app_id);
void rail_core_send_client_execute(RAIL_SESSION* session,
boolean exec_or_file_is_file_path, const char* rail_exe_or_file,
const char* rail_working_directory, const char* rail_arguments);
void rail_core_handle_ui_update_client_sysparam(RAIL_SESSION* session, RAIL_UI_EVENT* event);
#endif /* __RAIL_CORE_H */

View File

@ -28,22 +28,17 @@
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/rail.h>
#include "rail_core.h"
#include "rail_channel_orders.h"
#include "rail_orders.h"
#include "rail_main.h"
static void rail_plugin_process_connect(rdpSvcPlugin* plugin)
{
railPlugin* rail_plugin = (railPlugin*)plugin;
DEBUG_RAIL("rail_plugin_process_connect() called.");
rail_core_on_channel_connected(rail_plugin->session);
}
static void rail_plugin_process_terminate(rdpSvcPlugin* plugin)
{
DEBUG_RAIL("rail_plugin_process_terminate\n");
xfree(plugin);
}
static void rail_plugin_send_vchannel_data(void* rail_plugin_object, void* data, size_t length)
@ -51,35 +46,27 @@ static void rail_plugin_send_vchannel_data(void* rail_plugin_object, void* data,
STREAM* s = NULL;
railPlugin* plugin = (railPlugin*) rail_plugin_object;
DEBUG_RAIL("rail_plugin_send_vchannel_data\n");
s = stream_new(length);
stream_write(s, data, length);
svc_plugin_send((rdpSvcPlugin*) plugin, s);
}
static void rail_plugin_process_received_vchannel_data(rdpSvcPlugin* plugin, STREAM* data_in)
static void rail_plugin_process_received_vchannel_data(rdpSvcPlugin* plugin, STREAM* s)
{
railPlugin* rail_plugin = (railPlugin*) plugin;
DEBUG_RAIL("rail_plugin_process_receive: size=%d", stream_get_size(data_in));
DEBUG_RAIL("rail_plugin_process_received_vchannel_data\n");
rail_vchannel_process_received_vchannel_data(rail_plugin->session, data_in);
stream_free(data_in);
rail_order_recv(rail_plugin->rail, s);
stream_free(s);
}
static void on_free_rail_vchannel_event(FRDP_EVENT* event)
{
assert(event->event_type == FRDP_EVENT_TYPE_RAIL_VCHANNEL_2_UI);
RAIL_VCHANNEL_EVENT* rail_event = (RAIL_VCHANNEL_EVENT*)event->user_data;
if (rail_event->event_id == RAIL_VCHANNEL_EVENT_APP_RESPONSE_RECEIVED)
xfree((void*)rail_event->param.app_response_info.application_id);
if (rail_event->event_id == RAIL_VCHANNEL_EVENT_EXEC_RESULT_RETURNED)
xfree((void*)rail_event->param.exec_result_info.exe_or_file);
xfree(rail_event);
}
static void rail_plugin_send_vchannel_event(void* rail_plugin_object, RAIL_VCHANNEL_EVENT* event)
@ -88,6 +75,8 @@ static void rail_plugin_send_vchannel_event(void* rail_plugin_object, RAIL_VCHAN
RAIL_VCHANNEL_EVENT* payload = NULL;
FRDP_EVENT* out_event = NULL;
DEBUG_RAIL("rail_plugin_send_vchannel_event\n");
payload = xnew(RAIL_VCHANNEL_EVENT);
memset(payload, 0, sizeof(RAIL_VCHANNEL_EVENT));
memcpy(payload, event, sizeof(RAIL_VCHANNEL_EVENT));
@ -107,41 +96,42 @@ static void rail_plugin_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event)
rail_plugin = (railPlugin*)plugin;
rail_ui_event = (RAIL_UI_EVENT*)event->user_data;
if (event->event_type == FRDP_EVENT_TYPE_RAIL_UI_2_VCHANNEL)
rail_core_handle_ui_event(rail_plugin->session, rail_ui_event);
//if (event->event_type == FRDP_EVENT_TYPE_RAIL_UI_2_VCHANNEL)
//rail_core_handle_ui_event(rail_plugin->session, rail_ui_event);
freerdp_event_free(event);
}
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
railPlugin* rail;
railPlugin* rail_plugin;
DEBUG_RAIL("RAIL plugin VirtualChannelEntry started.");
rail = (railPlugin*) xzalloc(sizeof(railPlugin));
rail_plugin = (railPlugin*) xzalloc(sizeof(railPlugin));
rail->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED |
rail_plugin->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED |
CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP |
CHANNEL_OPTION_SHOW_PROTOCOL;
strcpy(rail->plugin.channel_def.name, "rail");
strcpy(rail_plugin->plugin.channel_def.name, "rail");
rail->plugin.connect_callback = rail_plugin_process_connect;
rail->plugin.terminate_callback = rail_plugin_process_terminate;
rail_plugin->plugin.connect_callback = rail_plugin_process_connect;
rail_plugin->plugin.terminate_callback = rail_plugin_process_terminate;
rail->plugin.receive_callback = rail_plugin_process_received_vchannel_data;
rail->plugin.event_callback = rail_plugin_process_event;
rail_plugin->plugin.receive_callback = rail_plugin_process_received_vchannel_data;
rail_plugin->plugin.event_callback = rail_plugin_process_event;
rail->rail_event_sender.event_sender_object = rail;
rail->rail_event_sender.send_rail_vchannel_event = rail_plugin_send_vchannel_event;
rail_plugin->rail_event_sender.event_sender_object = rail_plugin;
rail_plugin->rail_event_sender.send_rail_vchannel_event = rail_plugin_send_vchannel_event;
rail->rail_data_sender.data_sender_object = rail;
rail->rail_data_sender.send_rail_vchannel_data =
rail_plugin_send_vchannel_data;
rail_plugin->rail_data_sender.data_sender_object = rail_plugin;
rail_plugin->rail_data_sender.send_rail_vchannel_data = rail_plugin_send_vchannel_data;
rail->session = rail_core_session_new(&rail->rail_data_sender, &rail->rail_event_sender);
rail_plugin->rail = rail_new();
rail_plugin->rail->data_sender = &(rail_plugin->rail_data_sender);
rail_plugin->rail->event_sender = &(rail_plugin->rail_event_sender);
svc_plugin_init((rdpSvcPlugin*) rail, pEntryPoints);
svc_plugin_init((rdpSvcPlugin*) rail_plugin, pEntryPoints);
DEBUG_RAIL("RAIL plugin VirtualChannelEntry finished.");

View File

@ -22,13 +22,63 @@
#ifndef __RAIL_MAIN_H
#define __RAIL_MAIN_H
#include <freerdp/rail.h>
#include <freerdp/utils/stream.h>
#include <freerdp/utils/svc_plugin.h>
typedef struct _RAIL_VCHANNEL_DATA_SENDER RAIL_VCHANNEL_DATA_SENDER;
typedef struct _RAIL_VCHANNEL_EVENT_SENDER RAIL_VCHANNEL_EVENT_SENDER;
struct _RAIL_VCHANNEL_DATA_SENDER
{
void* data_sender_object;
void (*send_rail_vchannel_data)(void* sender_object, void* data, size_t length);
};
struct _RAIL_VCHANNEL_EVENT_SENDER
{
void * event_sender_object;
void (*send_rail_vchannel_event)(void* ui_event_sender_object, RAIL_VCHANNEL_EVENT* event);
};
struct rdp_rail
{
UNICONV* uniconv;
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_VCHANNEL_DATA_SENDER* data_sender;
RAIL_VCHANNEL_EVENT_SENDER* event_sender;
};
typedef struct rdp_rail rdpRail;
struct rail_plugin
{
rdpSvcPlugin plugin;
RAIL_VCHANNEL_DATA_SENDER rail_data_sender;
RAIL_VCHANNEL_EVENT_SENDER rail_event_sender;
RAIL_SESSION * session;
rdpRail* rail;
};
typedef struct rail_plugin railPlugin;
#define WITH_DEBUG_RAIL 1
#ifdef WITH_DEBUG_RAIL
#define DEBUG_RAIL(fmt, ...) DEBUG_CLASS(RAIL, fmt, ## __VA_ARGS__)
#else
#define DEBUG_RAIL(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif
#endif /* __RAIL_MAIN_H */

View File

@ -60,6 +60,23 @@ uint8 RAIL_ORDER_TYPE_STRINGS[][32] =
"Execute Result"
};
void rail_string_to_unicode_string(rdpRail* rail, char* string, UNICODE_STRING* unicode_string)
{
char* buffer;
size_t length = 0;
unicode_string->string = NULL;
unicode_string->length = 0;
if (strlen(string) < 1)
return;
buffer = freerdp_uniconv_out(rail->uniconv, string, &length);
unicode_string->string = (uint8*) buffer;
unicode_string->length = (uint16) length;
}
void rail_read_pdu_header(STREAM* s, uint16* orderType, uint16* orderLength)
{
stream_read_uint16(s, *orderType); /* orderType (2 bytes) */
@ -263,6 +280,67 @@ void rail_write_langbar_info_order(STREAM* s, RAIL_LANGBAR_INFO_ORDER* langbar_i
stream_write_uint32(s, langbar_info->languageBarStatus); /* languageBarStatus (4 bytes) */
}
void rail_recv_handshake_order(rdpRail* rail, STREAM* s)
{
rail_read_handshake_order(s, &rail->handshake);
rail->handshake.buildNumber = 0x00001DB1;
rail_send_handshake_order(rail);
rail->client_status.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE;
rail_send_client_status_order(rail);
/* sysparam update */
rail->sysparam.systemParam = SPI_SET_HIGH_CONTRAST;
rail->sysparam.highContrast.colorScheme.string = NULL;
rail->sysparam.highContrast.colorScheme.length = 0;
rail->sysparam.highContrast.flags = 0x7E;
rail_send_client_sysparam_order(rail);
rail->sysparam.systemParam = SPI_TASKBAR_POS;
rail->sysparam.rectangle.left = 0;
rail->sysparam.rectangle.top = 0;
rail->sysparam.rectangle.right = 1024;
rail->sysparam.rectangle.bottom = 29;
rail_send_client_sysparam_order(rail);
rail->sysparam.systemParam = SPI_SET_MOUSE_BUTTON_SWAP;
rail->sysparam.value = False;
rail_send_client_sysparam_order(rail);
rail->sysparam.systemParam = SPI_SET_KEYBOARD_PREF;
rail->sysparam.value = False;
rail_send_client_sysparam_order(rail);
rail->sysparam.systemParam = SPI_SET_DRAG_FULL_WINDOWS;
rail->sysparam.value = False;
rail_send_client_sysparam_order(rail);
rail->sysparam.systemParam = SPI_SET_KEYBOARD_CUES;
rail->sysparam.value = False;
rail_send_client_sysparam_order(rail);
rail->sysparam.systemParam = SPI_SET_WORK_AREA;
rail->sysparam.rectangle.left = 0;
rail->sysparam.rectangle.top = 0;
rail->sysparam.rectangle.right = 1024;
rail->sysparam.rectangle.bottom = 768;
rail_send_client_sysparam_order(rail);
/* execute */
rail->exec.flags =
RAIL_EXEC_FLAG_EXPAND_WORKINGDIRECTORY |
RAIL_EXEC_FLAG_EXPAND_ARGUMENTS;
rail_string_to_unicode_string(rail, "||cmd", &rail->exec.exeOrFile);
rail_string_to_unicode_string(rail, "", &rail->exec.workingDir);
rail_string_to_unicode_string(rail, "", &rail->exec.arguments);
rail_send_client_exec_order(rail);
}
void rail_order_recv(rdpRail* rail, STREAM* s)
{
uint16 orderType;
@ -276,7 +354,7 @@ void rail_order_recv(rdpRail* rail, STREAM* s)
switch (orderType)
{
case RDP_RAIL_ORDER_HANDSHAKE:
rail_read_handshake_order(s, &rail->handshake);
rail_recv_handshake_order(rail, s);
break;
case RDP_RAIL_ORDER_EXEC_RESULT:

View File

@ -21,34 +21,7 @@
#ifndef __RAIL_ORDERS_H
#define __RAIL_ORDERS_H
typedef struct rdp_rail rdpRail;
#include "rail_core.h"
#include <freerdp/rail.h>
#include <freerdp/utils/stream.h>
struct rdp_rail
{
UNICONV* uniconv;
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_VCHANNEL_DATA_SENDER* data_sender;
RAIL_VCHANNEL_EVENT_SENDER* event_sender;
};
#include "rail_main.h"
#define RAIL_ORDER_TYPE_EXEC 0x0001
#define RAIL_ORDER_TYPE_ACTIVATE 0x0002