mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-27 11:54:44 +08:00
rail: started integrating Roman's RAIL virtual channel plugin
This commit is contained in:
parent
510fb93b99
commit
b782189569
@ -21,4 +21,5 @@ add_subdirectory(cliprdr)
|
||||
add_subdirectory(drdynvc)
|
||||
add_subdirectory(rdpdbg)
|
||||
add_subdirectory(rdpdr)
|
||||
add_subdirectory(rail)
|
||||
|
||||
|
35
channels/rail/CMakeLists.txt
Normal file
35
channels/rail/CMakeLists.txt
Normal file
@ -0,0 +1,35 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Client
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2011 O.S. Systems Software Ltda.
|
||||
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
|
||||
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@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.
|
||||
|
||||
set(RAIL_SRCS
|
||||
rail_main.c
|
||||
rail_main.h
|
||||
rail_core.c
|
||||
rail_core.h
|
||||
rail_channel_orders.c
|
||||
rail_channel_orders.h
|
||||
)
|
||||
|
||||
add_library(rail SHARED ${RAIL_SRCS})
|
||||
set_target_properties(rail PROPERTIES PREFIX "")
|
||||
|
||||
target_link_libraries(rail freerdp-utils)
|
||||
|
||||
install(TARGETS rail DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
|
646
channels/rail/rail_channel_orders.c
Normal file
646
channels/rail/rail_channel_orders.c
Normal file
@ -0,0 +1,646 @@
|
||||
/*
|
||||
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/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);
|
||||
}
|
||||
|
||||
void write_rail_unicode_string_content(STREAM* s, RAIL_UNICODE_STRING* string)
|
||||
{
|
||||
if (string->length > 0)
|
||||
stream_write(s, string->buffer, string->length);
|
||||
}
|
||||
|
||||
void write_rail_unicode_string(STREAM* s, RAIL_UNICODE_STRING* string)
|
||||
{
|
||||
stream_write_uint16(s, string->length);
|
||||
|
||||
if (string->length > 0)
|
||||
stream_write(s, string->buffer, string->length);
|
||||
}
|
||||
|
||||
void write_rail_rect_16(STREAM* s, RAIL_RECT_16* rect)
|
||||
{
|
||||
stream_write_uint16(s, rect->left); /*Left*/
|
||||
stream_write_uint16(s, rect->top); /*Top*/
|
||||
stream_write_uint16(s, rect->right); /*Right*/
|
||||
stream_write_uint16(s, rect->bottom); /*Bottom*/
|
||||
}
|
||||
|
||||
void read_rail_unicode_string(STREAM* s, RAIL_UNICODE_STRING * string)
|
||||
{
|
||||
stream_read_uint16(s, string->length);
|
||||
|
||||
string->buffer = NULL;
|
||||
if (string->length > 0)
|
||||
{
|
||||
string->buffer = xmalloc(string->length);
|
||||
stream_read(s, string->buffer, string->length);
|
||||
}
|
||||
}
|
||||
|
||||
void free_rail_unicode_string(RAIL_UNICODE_STRING * string)
|
||||
{
|
||||
if (string->buffer != NULL)
|
||||
{
|
||||
xfree(string->buffer);
|
||||
string->buffer = NULL;
|
||||
string->length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
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,
|
||||
RAIL_UNICODE_STRING* exe_or_file, RAIL_UNICODE_STRING* working_directory, RAIL_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);
|
||||
|
||||
write_rail_unicode_string_content(s, exe_or_file);
|
||||
write_rail_unicode_string_content(s, working_directory);
|
||||
write_rail_unicode_string_content(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_SETDRAGFULLWINDOWS: {return 1;}
|
||||
case SPI_SETKEYBOARDCUES: {return 1;}
|
||||
case SPI_SETKEYBOARDPREF: {return 1;}
|
||||
case SPI_SETMOUSEBUTTONSWAP: {return 1;}
|
||||
case SPI_SETWORKAREA: {return 8;}
|
||||
case RAIL_SPI_DISPLAYCHANGE: {return 8;}
|
||||
case RAIL_SPI_TASKBARPOS: {return 8;}
|
||||
case SPI_SETHIGHCONTRAST:
|
||||
{
|
||||
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_SETDRAGFULLWINDOWS:
|
||||
stream_write_uint8(s, sysparam->value.full_window_drag_enabled);
|
||||
break;
|
||||
|
||||
case SPI_SETKEYBOARDCUES:
|
||||
stream_write_uint8(s, sysparam->value.menu_access_key_always_underlined);
|
||||
break;
|
||||
|
||||
case SPI_SETKEYBOARDPREF:
|
||||
stream_write_uint8(s, sysparam->value.keyboard_for_user_prefered);
|
||||
break;
|
||||
|
||||
case SPI_SETMOUSEBUTTONSWAP:
|
||||
stream_write_uint8(s, sysparam->value.left_right_mouse_buttons_swapped);
|
||||
break;
|
||||
|
||||
case SPI_SETWORKAREA:
|
||||
write_rail_rect_16(s, &sysparam->value.work_area);
|
||||
break;
|
||||
|
||||
case RAIL_SPI_DISPLAYCHANGE:
|
||||
write_rail_rect_16(s, &sysparam->value.display_resolution);
|
||||
break;
|
||||
|
||||
case RAIL_SPI_TASKBARPOS:
|
||||
write_rail_rect_16(s, &sysparam->value.taskbar_size);
|
||||
break;
|
||||
|
||||
case SPI_SETHIGHCONTRAST:
|
||||
{
|
||||
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);
|
||||
write_rail_unicode_string(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, RAIL_RECT_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);
|
||||
|
||||
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;
|
||||
RAIL_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)*/
|
||||
read_rail_unicode_string(s, &exe_or_file); /*ExeOrFileLength with ExeOrFile (variable)*/
|
||||
|
||||
rail_core_handle_exec_result(session, flags, exec_result, raw_result, &exe_or_file);
|
||||
free_rail_unicode_string(&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_SETSCREENSAVEACTIVE:
|
||||
stream_read_uint8(s, sysparam.value.screen_saver_enabled);
|
||||
break;
|
||||
|
||||
case SPI_SETSCREENSAVESECURE:
|
||||
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;
|
||||
RAIL_UNICODE_STRING app_id = {0};
|
||||
|
||||
app_id.length = 256;
|
||||
app_id.buffer = xmalloc(app_id.length);
|
||||
|
||||
stream_read_uint32(s, window_id);
|
||||
stream_read(s, app_id.buffer, app_id.length);
|
||||
|
||||
rail_core_handle_server_get_app_resp(session, window_id, &app_id);
|
||||
free_rail_unicode_string(&app_id);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
40
channels/rail/rail_channel_orders.h
Normal file
40
channels/rail/rail_channel_orders.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
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, RAIL_UNICODE_STRING* exe_or_file,
|
||||
RAIL_UNICODE_STRING* working_directory, RAIL_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, RAIL_RECT_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 */
|
471
channels/rail/rail_core.c
Normal file
471
channels/rail/rail_core.c
Normal file
@ -0,0 +1,471 @@
|
||||
/**
|
||||
* 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/svc_plugin.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_string2unicode_string(RAIL_SESSION* session, RAIL_STRING* string, RAIL_UNICODE_STRING* unicode_string)
|
||||
{
|
||||
size_t result_length = 0;
|
||||
char* result_buffer = NULL;
|
||||
|
||||
unicode_string->buffer = NULL;
|
||||
unicode_string->length = 0;
|
||||
|
||||
if (string->length == 0) return;
|
||||
|
||||
result_buffer = freerdp_uniconv_out(session->uniconv, (char*) string->buffer, &result_length);
|
||||
|
||||
unicode_string->buffer = (uint8*)result_buffer;
|
||||
unicode_string->length = (uint16)result_length;
|
||||
}
|
||||
|
||||
void rail_unicode_string2string(RAIL_SESSION* session, RAIL_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->buffer, 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();
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void rail_core_session_free(RAIL_SESSION* rail_session)
|
||||
{
|
||||
if (rail_session != NULL)
|
||||
{
|
||||
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)
|
||||
{
|
||||
uint32 client_build_number = 0x00001db0;
|
||||
RAIL_VCHANNEL_EVENT event = {0};
|
||||
|
||||
DEBUG_RAIL("rail_core_handle_server_hadshake: 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);
|
||||
}
|
||||
|
||||
void rail_core_handle_exec_result(RAIL_SESSION* session, uint16 flags, uint16 exec_result, uint32 raw_result, RAIL_UNICODE_STRING* exe_or_file)
|
||||
{
|
||||
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->buffer, 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);
|
||||
}
|
||||
|
||||
void rail_core_handle_server_sysparam(RAIL_SESSION* session, RAIL_SERVER_SYSPARAM* sysparam)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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, RAIL_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->buffer, 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_;
|
||||
RAIL_UNICODE_STRING exe_or_file;
|
||||
RAIL_UNICODE_STRING working_directory;
|
||||
RAIL_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);
|
||||
|
||||
free_rail_unicode_string(&exe_or_file);
|
||||
free_rail_unicode_string(&working_directory);
|
||||
free_rail_unicode_string(&arguments);
|
||||
}
|
||||
|
||||
uint8 boolean2uint8(boolean value)
|
||||
{
|
||||
return ((value == True) ? 1 : 0);
|
||||
}
|
||||
|
||||
uint8 copy_rail_rect_16(RAIL_RECT_16* src, RAIL_RECT_16* dst)
|
||||
{
|
||||
memcpy(dst, src, sizeof(RAIL_RECT_16));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static 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_SETHIGHCONTRAST)
|
||||
{
|
||||
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);
|
||||
free_rail_unicode_string(&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)
|
||||
{
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
137
channels/rail/rail_core.h
Normal file
137
channels/rail/rail_core.h
Normal file
@ -0,0 +1,137 @@
|
||||
/**
|
||||
* 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>
|
||||
|
||||
#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;
|
||||
RAIL_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;
|
||||
RAIL_RECT_16 work_area;
|
||||
RAIL_RECT_16 display_resolution;
|
||||
RAIL_RECT_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);
|
||||
};
|
||||
typedef struct _RAIL_VCHANNEL_DATA_SENDER RAIL_VCHANNEL_DATA_SENDER;
|
||||
|
||||
struct _RAIL_VCHANNEL_EVENT_SENDER
|
||||
{
|
||||
void * event_sender_object;
|
||||
void (*send_rail_vchannel_event)(void* ui_event_sender_object, RAIL_VCHANNEL_EVENT* event);
|
||||
};
|
||||
typedef struct _RAIL_VCHANNEL_EVENT_SENDER RAIL_VCHANNEL_EVENT_SENDER;
|
||||
|
||||
struct _RAIL_SESSION
|
||||
{
|
||||
UNICONV * uniconv;
|
||||
RAIL_VCHANNEL_DATA_SENDER* data_sender;
|
||||
RAIL_VCHANNEL_EVENT_SENDER* event_sender;
|
||||
};
|
||||
typedef struct _RAIL_SESSION RAIL_SESSION;
|
||||
|
||||
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, RAIL_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, RAIL_UNICODE_STRING* app_id);
|
||||
|
||||
#endif /* __RAIL_CORE_H */
|
149
channels/rail/rail_main.c
Normal file
149
channels/rail/rail_main.c
Normal file
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* RAIL Virtual Channel Plugin
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2011 Roman Barabanov <romanbarabanov@gmail.com>
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* 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/svc_plugin.h>
|
||||
#include <freerdp/rail.h>
|
||||
|
||||
#include "rail_core.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)
|
||||
{
|
||||
STREAM* s = NULL;
|
||||
railPlugin* plugin = (railPlugin*) rail_plugin_object;
|
||||
|
||||
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)
|
||||
{
|
||||
railPlugin* rail_plugin = (railPlugin*) plugin;
|
||||
|
||||
DEBUG_RAIL("rail_plugin_process_receive: size=%d", stream_get_size(data_in));
|
||||
|
||||
rail_vchannel_process_received_vchannel_data(rail_plugin->session, data_in);
|
||||
stream_free(data_in);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
railPlugin* plugin = (railPlugin*) rail_plugin_object;
|
||||
RAIL_VCHANNEL_EVENT* payload = NULL;
|
||||
FRDP_EVENT* out_event = NULL;
|
||||
|
||||
payload = xnew(RAIL_VCHANNEL_EVENT);
|
||||
memset(payload, 0, sizeof(RAIL_VCHANNEL_EVENT));
|
||||
memcpy(payload, event, sizeof(RAIL_VCHANNEL_EVENT));
|
||||
|
||||
out_event = freerdp_event_new(FRDP_EVENT_TYPE_RAIL_VCHANNEL_2_UI, on_free_rail_vchannel_event, payload);
|
||||
|
||||
svc_plugin_send_event((rdpSvcPlugin*) plugin, out_event);
|
||||
}
|
||||
|
||||
static void rail_plugin_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event)
|
||||
{
|
||||
RAIL_UI_EVENT* rail_ui_event = NULL;
|
||||
railPlugin* rail_plugin = NULL;
|
||||
|
||||
DEBUG_RAIL("rail_plugin_process_event: event_type=%d\n", event->event_type);
|
||||
|
||||
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);
|
||||
|
||||
freerdp_event_free(event);
|
||||
}
|
||||
|
||||
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
railPlugin* rail;
|
||||
|
||||
DEBUG_RAIL("RAIL plugin VirtualChannelEntry started.");
|
||||
|
||||
rail = (railPlugin*) xzalloc(sizeof(railPlugin));
|
||||
|
||||
rail->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");
|
||||
|
||||
rail->plugin.connect_callback = rail_plugin_process_connect;
|
||||
rail->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->rail_event_sender.event_sender_object = rail;
|
||||
rail->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->session = rail_core_session_new(&rail->rail_data_sender, &rail->rail_event_sender);
|
||||
|
||||
svc_plugin_init((rdpSvcPlugin*) rail, pEntryPoints);
|
||||
|
||||
DEBUG_RAIL("RAIL plugin VirtualChannelEntry finished.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
34
channels/rail/rail_main.h
Normal file
34
channels/rail/rail_main.h
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* RAIL Virtual Channel Plugin
|
||||
*
|
||||
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2011 Roman Barabanov <romanbarabanov@gmail.com>
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
* 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_MAIN_H
|
||||
#define __RAIL_MAIN_H
|
||||
|
||||
struct rail_plugin
|
||||
{
|
||||
rdpSvcPlugin plugin;
|
||||
RAIL_VCHANNEL_DATA_SENDER rail_data_sender;
|
||||
RAIL_VCHANNEL_EVENT_SENDER rail_event_sender;
|
||||
RAIL_SESSION * session;
|
||||
};
|
||||
typedef struct rail_plugin railPlugin;
|
||||
|
||||
#endif /* __RAIL_MAIN_H */
|
@ -407,7 +407,8 @@ boolean disk_file_set_information(DISK_FILE* file, uint32 FsInformationClass, ui
|
||||
case FileAllocationInformation:
|
||||
/* http://msdn.microsoft.com/en-us/library/cc232076.aspx */
|
||||
stream_read_uint64(input, size);
|
||||
ftruncate(file->fd, size);
|
||||
if (ftruncate(file->fd, size) != 0)
|
||||
return False;
|
||||
break;
|
||||
|
||||
case FileDispositionInformation:
|
||||
|
@ -81,7 +81,10 @@ enum FRDP_EVENT_TYPE
|
||||
FRDP_EVENT_TYPE_CB_SYNC = 3,
|
||||
FRDP_EVENT_TYPE_CB_FORMAT_LIST = 4,
|
||||
FRDP_EVENT_TYPE_CB_DATA_REQUEST = 5,
|
||||
FRDP_EVENT_TYPE_CB_DATA_RESPONSE = 6
|
||||
FRDP_EVENT_TYPE_CB_DATA_RESPONSE = 6,
|
||||
|
||||
FRDP_EVENT_TYPE_RAIL_UI_2_VCHANNEL = 100,
|
||||
FRDP_EVENT_TYPE_RAIL_VCHANNEL_2_UI = 101
|
||||
};
|
||||
|
||||
/**
|
||||
|
341
include/freerdp/rail.h
Normal file
341
include/freerdp/rail.h
Normal file
@ -0,0 +1,341 @@
|
||||
/**
|
||||
* 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_H
|
||||
#define __RAIL_H
|
||||
|
||||
/* RAIL Constants*/
|
||||
|
||||
enum RDP_RAIL_PDU_TYPE
|
||||
{
|
||||
RDP_RAIL_ORDER_EXEC = 0x0001,
|
||||
RDP_RAIL_ORDER_ACTIVATE = 0x0002,
|
||||
RDP_RAIL_ORDER_SYSPARAM = 0x0003,
|
||||
RDP_RAIL_ORDER_SYSCOMMAND = 0x0004,
|
||||
RDP_RAIL_ORDER_HANDSHAKE = 0x0005,
|
||||
RDP_RAIL_ORDER_NOTIFY_EVENT = 0x0006,
|
||||
RDP_RAIL_ORDER_WINDOWMOVE = 0x0008,
|
||||
RDP_RAIL_ORDER_LOCALMOVESIZE = 0x0009,
|
||||
RDP_RAIL_ORDER_MINMAXINFO = 0x000A,
|
||||
RDP_RAIL_ORDER_CLIENTSTATUS = 0x000B,
|
||||
RDP_RAIL_ORDER_SYSMENU = 0x000C,
|
||||
RDP_RAIL_ORDER_LANGBARINFO = 0x000D,
|
||||
RDP_RAIL_ORDER_EXEC_RESULT = 0x0080,
|
||||
RDP_RAIL_ORDER_GET_APPID_REQ = 0x000E,
|
||||
RDP_RAIL_ORDER_GET_APPID_RESP = 0x000F
|
||||
};
|
||||
|
||||
/* RAIL PDU flags */
|
||||
#define RAIL_EXEC_FLAG_EXPAND_WORKINGDIRECTORY 0x0001
|
||||
#define RAIL_EXEC_FLAG_TRANSLATE_FILES 0x0002
|
||||
#define RAIL_EXEC_FLAG_FILE 0x0004
|
||||
#define RAIL_EXEC_FLAG_EXPAND_ARGUMENTS 0x0008
|
||||
|
||||
/* Notification Icon Balloon Tooltip */
|
||||
#define NIIF_NONE 0x00000000
|
||||
#define NIIF_INFO 0x00000001
|
||||
#define NIIF_WARNING 0x00000002
|
||||
#define NIIF_ERROR 0x00000003
|
||||
#define NIIF_NOSOUND 0x00000010
|
||||
#define NIIF_LARGE_ICON 0x00000020
|
||||
|
||||
/* Client Execute PDU Flags */
|
||||
#define RAIL_EXEC_FLAG_EXPAND_WORKING_DIRECTORY 0x0001
|
||||
#define RAIL_EXEC_FLAG_TRANSLATE_FILES 0x0002
|
||||
#define RAIL_EXEC_FLAG_FILE 0x0004
|
||||
#define RAIL_EXEC_FLAG_EXPAND_ARGUMENTS 0x0008
|
||||
|
||||
/* Server Execute Result PDU */
|
||||
#define RAIL_EXEC_S_OK 0x0000
|
||||
#define RAIL_EXEC_E_HOOK_NOT_LOADED 0x0001
|
||||
#define RAIL_EXEC_E_DECODE_FAILED 0x0002
|
||||
#define RAIL_EXEC_E_NOT_IN_ALLOWLIST 0x0003
|
||||
#define RAIL_EXEC_E_FILE_NOT_FOUND 0x0005
|
||||
#define RAIL_EXEC_E_FAIL 0x0006
|
||||
#define RAIL_EXEC_E_SESSION_LOCKED 0x0007
|
||||
|
||||
/* Client System Parameters Update PDU */
|
||||
#define SPI_SETDRAGFULLWINDOWS 0x00000025
|
||||
#define SPI_SETKEYBOARDCUES 0x0000100B
|
||||
#define SPI_SETKEYBOARDPREF 0x00000045
|
||||
#define SPI_SETWORKAREA 0x0000002F
|
||||
#define SPI_SETMOUSEBUTTONSWAP 0x00000021
|
||||
#define SPI_SETHIGHCONTRAST 0x00000043
|
||||
#define RAIL_SPI_DISPLAYCHANGE 0x0000F001
|
||||
#define RAIL_SPI_TASKBARPOS 0x0000F000
|
||||
|
||||
/* Server System Parameters Update PDU */
|
||||
#define SPI_SETSCREENSAVEACTIVE 0x00000011
|
||||
#define SPI_SETSCREENSAVESECURE 0x00000077
|
||||
|
||||
/* Client System Command PDU */
|
||||
#define SC_SIZE 0xF000
|
||||
#define SC_MOVE 0xF010
|
||||
#define SC_MINIMIZE 0xF020
|
||||
#define SC_MAXIMIZE 0xF030
|
||||
#define SC_CLOSE 0xF060
|
||||
#define SC_KEYMENU 0xF100
|
||||
#define SC_RESTORE 0xF120
|
||||
#define SC_DEFAULT 0xF160
|
||||
|
||||
/* Client Notify Event PDU */
|
||||
#define WM_LBUTTONDOWN 0x00000201
|
||||
#define WM_LBUTTONUP 0x00000202
|
||||
#define WM_RBUTTONDOWN 0x00000204
|
||||
#define WM_RBUTTONUP 0x00000205
|
||||
#define WM_CONTEXTMENU 0x0000007B
|
||||
#define WM_LBUTTONDBLCLK 0x00000203
|
||||
#define WM_RBUTTONDBLCLK 0x00000206
|
||||
|
||||
#define NIN_SELECT 0x00000400
|
||||
#define NIN_KEYSELECT 0x00000401
|
||||
#define NIN_BALLOONSHOW 0x00000402
|
||||
#define NIN_BALLOONHIDE 0x00000403
|
||||
#define NIN_BALLOONTIMEOUT 0x00000404
|
||||
#define NIN_BALLOONUSERCLICK 0x00000405
|
||||
|
||||
/* Client Information PDU */
|
||||
#define RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE 0x00000001
|
||||
#define RAIL_CLIENTSTATUS_AUTORECONNECT 0x00000002
|
||||
|
||||
/*HIGHCONTRAST flags values */
|
||||
#define HCF_AVAILABLE 0x00000002
|
||||
#define HCF_CONFIRMHOTKEY 0x00000008
|
||||
#define HCF_HIGHCONTRASTON 0x00000001
|
||||
#define HCF_HOTKEYACTIVE 0x00000004
|
||||
#define HCF_HOTKEYAVAILABLE 0x00000040
|
||||
#define HCF_HOTKEYSOUND 0x00000010
|
||||
#define HCF_INDICATOR 0x00000020
|
||||
|
||||
/* Server Move/Size Start PDU */
|
||||
#define RAIL_WMSZ_LEFT 0x0001
|
||||
#define RAIL_WMSZ_RIGHT 0x0002
|
||||
#define RAIL_WMSZ_TOP 0x0003
|
||||
#define RAIL_WMSZ_TOPLEFT 0x0004
|
||||
#define RAIL_WMSZ_TOPRIGHT 0x0005
|
||||
#define RAIL_WMSZ_BOTTOM 0x0006
|
||||
#define RAIL_WMSZ_BOTTOMLEFT 0x0007
|
||||
#define RAIL_WMSZ_BOTTOMRIGHT 0x0008
|
||||
#define RAIL_WMSZ_MOVE 0x0009
|
||||
#define RAIL_WMSZ_KEYMOVE 0x000A
|
||||
#define RAIL_WMSZ_KEYSIZE 0x000B
|
||||
|
||||
/* Language Bar Information PDU */
|
||||
#define TF_SFT_SHOWNORMAL 0x00000001
|
||||
#define TF_SFT_DOCK 0x00000002
|
||||
#define TF_SFT_MINIMIZED 0x00000004
|
||||
#define TF_SFT_HIDDEN 0x00000008
|
||||
#define TF_SFT_NOTRANSPARENCY 0x00000010
|
||||
#define TF_SFT_LOWTRANSPARENCY 0x00000020
|
||||
#define TF_SFT_HIGHTRANSPARENCY 0x00000040
|
||||
#define TF_SFT_LABELS 0x00000080
|
||||
#define TF_SFT_NOLABELS 0x00000100
|
||||
#define TF_SFT_EXTRAICONSONMINIMIZED 0x00000200
|
||||
#define TF_SFT_NOEXTRAICONSONMINIMIZED 0x00000400
|
||||
#define TF_SFT_DESKBAND 0x00000800
|
||||
|
||||
/* RAIL Common structures */
|
||||
|
||||
typedef struct _RAIL_RECT_16
|
||||
{
|
||||
uint16 left;
|
||||
uint16 top;
|
||||
uint16 right;
|
||||
uint16 bottom;
|
||||
}
|
||||
RAIL_RECT_16;
|
||||
|
||||
typedef struct _RAIL_UNICODE_STRING
|
||||
{
|
||||
uint16 length;
|
||||
uint8 *buffer;
|
||||
}
|
||||
RAIL_UNICODE_STRING;
|
||||
|
||||
// Events from 'rail' vchannel plugin to UI
|
||||
enum RAIL_VCHANNEL_EVENT
|
||||
{
|
||||
RAIL_VCHANNEL_EVENT_SESSION_ESTABLISHED = 1,
|
||||
RAIL_VCHANNEL_EVENT_EXEC_RESULT_RETURNED,
|
||||
RAIL_VCHANNEL_EVENT_SERVER_SYSPARAM_RECEIVED,
|
||||
RAIL_VCHANNEL_EVENT_MOVESIZE_STARTED,
|
||||
RAIL_VCHANNEL_EVENT_MOVESIZE_FINISHED,
|
||||
RAIL_VCHANNEL_EVENT_MINMAX_INFO_UPDATED,
|
||||
RAIL_VCHANNEL_EVENT_LANGBAR_STATUS_UPDATED,
|
||||
RAIL_VCHANNEL_EVENT_APP_RESPONSE_RECEIVED
|
||||
};
|
||||
|
||||
typedef struct _RAIL_VCHANNEL_EVENT
|
||||
{
|
||||
uint32 event_id;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16 flags;
|
||||
uint16 exec_result;
|
||||
uint32 raw_result;
|
||||
const char* exe_or_file;
|
||||
} exec_result_info;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 param_type;
|
||||
boolean screen_saver_enabled;
|
||||
boolean screen_saver_lock_enabled;
|
||||
} server_param_info;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 window_id;
|
||||
uint16 move_size_type;
|
||||
uint16 pos_x;
|
||||
uint16 pos_y;
|
||||
} movesize_info;
|
||||
|
||||
struct
|
||||
{
|
||||
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;
|
||||
} minmax_info;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 status;
|
||||
} langbar_info;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 window_id;
|
||||
const char* application_id;
|
||||
|
||||
} app_response_info;
|
||||
|
||||
}param;
|
||||
}
|
||||
RAIL_VCHANNEL_EVENT;
|
||||
|
||||
// Events from UI to 'rail' vchannel plugin
|
||||
enum RAIL_UI_EVENT
|
||||
{
|
||||
RAIL_UI_EVENT_UPDATE_CLIENT_SYSPARAM = 1,
|
||||
RAIL_UI_EVENT_EXECUTE_REMOTE_APP,
|
||||
RAIL_UI_EVENT_ACTIVATE,
|
||||
RAIL_UI_EVENT_SYS_COMMAND,
|
||||
RAIL_UI_EVENT_NOTIFY,
|
||||
RAIL_UI_EVENT_WINDOW_MOVE,
|
||||
RAIL_UI_EVENT_SYSTEM_MENU,
|
||||
RAIL_UI_EVENT_LANGBAR_INFO,
|
||||
RAIL_UI_EVENT_GET_APP_ID
|
||||
};
|
||||
|
||||
typedef struct _RAIL_UI_EVENT
|
||||
{
|
||||
uint32 event_id;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 param;
|
||||
|
||||
union
|
||||
{
|
||||
boolean full_window_drag_enabled;
|
||||
boolean menu_access_key_always_underlined;
|
||||
boolean keyboard_for_user_prefered;
|
||||
boolean left_right_mouse_buttons_swapped;
|
||||
RAIL_RECT_16 work_area;
|
||||
RAIL_RECT_16 display_resolution;
|
||||
RAIL_RECT_16 taskbar_size;
|
||||
struct
|
||||
{
|
||||
uint32 flags;
|
||||
const char* color_scheme;
|
||||
} high_contrast_system_info;
|
||||
} value;
|
||||
|
||||
} sysparam_info;
|
||||
|
||||
struct
|
||||
{
|
||||
boolean exec_or_file_is_file_path;
|
||||
const char* exe_or_file;
|
||||
const char* working_directory;
|
||||
const char* arguments;
|
||||
} execute_info;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 window_id;
|
||||
boolean enabled;
|
||||
} activate_info;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 window_id;
|
||||
uint32 syscommand;
|
||||
} syscommand_info;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 window_id;
|
||||
uint32 notify_icon_id;
|
||||
uint32 message;
|
||||
} notify_info;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 window_id;
|
||||
RAIL_RECT_16 new_position;
|
||||
} window_move_info;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 window_id;
|
||||
uint16 left;
|
||||
uint16 top;
|
||||
} system_menu_info;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 status;
|
||||
} langbar_info;
|
||||
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 window_id;
|
||||
} get_app_id_info;
|
||||
} param;
|
||||
}
|
||||
RAIL_UI_EVENT;
|
||||
|
||||
|
||||
#endif /* __RAIL_H */
|
||||
|
@ -50,6 +50,10 @@ FRDP_EVENT* freerdp_event_new(uint32 event_type, FRDP_EVENT_CALLBACK on_event_fr
|
||||
case FRDP_EVENT_TYPE_CB_DATA_RESPONSE:
|
||||
event = (FRDP_EVENT*)xnew(FRDP_CB_DATA_RESPONSE_EVENT);
|
||||
break;
|
||||
case FRDP_EVENT_TYPE_RAIL_UI_2_VCHANNEL:
|
||||
case FRDP_EVENT_TYPE_RAIL_VCHANNEL_2_UI:
|
||||
event = xnew(FRDP_EVENT);
|
||||
break;
|
||||
}
|
||||
if (event != NULL)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user