Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Emmanuel Ledoux 2014-07-03 11:56:00 +02:00 committed by Emmanuel Ledoux
commit e4840d3596
57 changed files with 4788 additions and 156 deletions

1
.gitignore vendored
View File

@ -113,6 +113,7 @@ Release
Win32
build*/
*.orig
*.msrcIncident
default.log
*Amplifier XE*

View File

@ -409,7 +409,8 @@ int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId
if (channel->status == 0)
{
pCallback = channel->channel_callback;
pCallback->OnOpen(pCallback);
if (pCallback->OnOpen)
pCallback->OnOpen(pCallback);
}
return 0;

View File

@ -0,0 +1,26 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 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.
define_channel("encomsp")
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -0,0 +1,13 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT ON)
define_channel_options(NAME "encomsp" TYPE "static"
DESCRIPTION "Multiparty Virtual Channel Extension"
SPECIFICATIONS "[MS-RDPEMC]"
DEFAULT ${OPTION_DEFAULT})
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})

View File

@ -0,0 +1,35 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 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.
define_channel_client("encomsp")
set(${MODULE_PREFIX}_SRCS
encomsp_main.c
encomsp_main.h)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-crt)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -0,0 +1,948 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Multiparty Virtual Channel
*
* Copyright 2014 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <freerdp/client/encomsp.h>
#include "encomsp_main.h"
EncomspClientContext* encomsp_get_client_interface(encomspPlugin* encomsp)
{
EncomspClientContext* pInterface;
pInterface = (EncomspClientContext*) encomsp->channelEntryPoints.pInterface;
return pInterface;
}
int encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s)
{
UINT32 status = 0;
if (!encomsp)
return -1;
#if 0
printf("EncomspWrite (%d)\n", Stream_Length(s));
winpr_HexDump(Stream_Buffer(s), Stream_Length(s));
#endif
status = encomsp->channelEntryPoints.pVirtualChannelWrite(encomsp->OpenHandle,
Stream_Buffer(s), (UINT32) Stream_Length(s), s);
if (status != CHANNEL_RC_OK)
{
fprintf(stderr, "encomsp_virtual_channel_write: VirtualChannelWrite failed %d\n", status);
return -1;
}
return 1;
}
int encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header)
{
if (Stream_GetRemainingLength(s) < ENCOMSP_ORDER_HEADER_SIZE)
return -1;
Stream_Read_UINT16(s, header->Type); /* Type (2 bytes) */
Stream_Read_UINT16(s, header->Length); /* Length (2 bytes) */
return 1;
}
int encomsp_write_header(wStream* s, ENCOMSP_ORDER_HEADER* header)
{
Stream_Write_UINT16(s, header->Type); /* Type (2 bytes) */
Stream_Write_UINT16(s, header->Length); /* Length (2 bytes) */
return 1;
}
int encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str)
{
ZeroMemory(str, sizeof(ENCOMSP_UNICODE_STRING));
if (Stream_GetRemainingLength(s) < 2)
return -1;
Stream_Read_UINT16(s, str->cchString); /* cchString (2 bytes) */
if (str->cchString > 1024)
return -1;
if (Stream_GetRemainingLength(s) < (str->cchString * 2))
return -1;
Stream_Read(s, &(str->wString), (str->cchString * 2)); /* String (variable) */
return 1;
}
int encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_FILTER_UPDATED_PDU pdu;
context = encomsp_get_client_interface(encomsp);
if (!context)
return -1;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 1)
return -1;
Stream_Read_UINT8(s, pdu.Flags); /* Flags (1 byte) */
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
return -1;
if ((beg + header->Length) > end)
{
if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
return -1;
Stream_SetPosition(s, (beg + header->Length));
}
if (context->FilterUpdated)
{
return context->FilterUpdated(context, &pdu);
}
return 1;
}
int encomsp_recv_application_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_APPLICATION_CREATED_PDU pdu;
context = encomsp_get_client_interface(encomsp);
if (!context)
return -1;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 6)
return -1;
Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */
Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */
if (encomsp_read_unicode_string(s, &(pdu.Name)) < 0)
return -1;
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
return -1;
if ((beg + header->Length) > end)
{
if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
return -1;
Stream_SetPosition(s, (beg + header->Length));
}
if (context->ApplicationCreated)
{
return context->ApplicationCreated(context, &pdu);
}
return 1;
}
int encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_APPLICATION_REMOVED_PDU pdu;
context = encomsp_get_client_interface(encomsp);
if (!context)
return -1;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 4)
return -1;
Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
return -1;
if ((beg + header->Length) > end)
{
if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
return -1;
Stream_SetPosition(s, (beg + header->Length));
}
if (context->ApplicationRemoved)
{
return context->ApplicationRemoved(context, &pdu);
}
return 1;
}
int encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_WINDOW_CREATED_PDU pdu;
context = encomsp_get_client_interface(encomsp);
if (!context)
return -1;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 10)
return -1;
Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */
Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */
Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */
if (encomsp_read_unicode_string(s, &(pdu.Name)) < 0)
return -1;
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
return -1;
if ((beg + header->Length) > end)
{
if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
return -1;
Stream_SetPosition(s, (beg + header->Length));
}
if (context->WindowCreated)
{
return context->WindowCreated(context, &pdu);
}
return 1;
}
int encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_WINDOW_REMOVED_PDU pdu;
context = encomsp_get_client_interface(encomsp);
if (!context)
return -1;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 4)
return -1;
Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
return -1;
if ((beg + header->Length) > end)
{
if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
return -1;
Stream_SetPosition(s, (beg + header->Length));
}
if (context->WindowRemoved)
{
return context->WindowRemoved(context, &pdu);
}
return 1;
}
int encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_SHOW_WINDOW_PDU pdu;
context = encomsp_get_client_interface(encomsp);
if (!context)
return -1;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 4)
return -1;
Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
return -1;
if ((beg + header->Length) > end)
{
if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
return -1;
Stream_SetPosition(s, (beg + header->Length));
}
if (context->ShowWindow)
{
return context->ShowWindow(context, &pdu);
}
return 1;
}
int encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_PARTICIPANT_CREATED_PDU pdu;
context = encomsp_get_client_interface(encomsp);
if (!context)
return -1;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 10)
return -1;
Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */
Stream_Read_UINT32(s, pdu.GroupId); /* GroupId (4 bytes) */
Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */
if (encomsp_read_unicode_string(s, &(pdu.FriendlyName)) < 0)
return -1;
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
return -1;
if ((beg + header->Length) > end)
{
if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
return -1;
Stream_SetPosition(s, (beg + header->Length));
}
if (context->ParticipantCreated)
{
return context->ParticipantCreated(context, &pdu);
}
return 1;
}
int encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_PARTICIPANT_REMOVED_PDU pdu;
context = encomsp_get_client_interface(encomsp);
if (!context)
return -1;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 12)
return -1;
Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */
Stream_Read_UINT32(s, pdu.DiscType); /* DiscType (4 bytes) */
Stream_Read_UINT32(s, pdu.DiscCode); /* DiscCode (4 bytes) */
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
return -1;
if ((beg + header->Length) > end)
{
if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
return -1;
Stream_SetPosition(s, (beg + header->Length));
}
if (context->ParticipantRemoved)
{
return context->ParticipantRemoved(context, &pdu);
}
return 1;
}
int encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu;
context = encomsp_get_client_interface(encomsp);
if (!context)
return -1;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
if (Stream_GetRemainingLength(s) < 6)
return -1;
Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */
Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
return -1;
if ((beg + header->Length) > end)
{
if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
return -1;
Stream_SetPosition(s, (beg + header->Length));
}
if (context->ChangeParticipantControlLevel)
{
return context->ChangeParticipantControlLevel(context, &pdu);
}
return 1;
}
int encomsp_send_change_participant_control_level_pdu(EncomspClientContext* context, ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* pdu)
{
wStream* s;
encomspPlugin* encomsp;
encomsp = (encomspPlugin*) context->handle;
pdu->Type = ODTYPE_PARTICIPANT_CTRL_CHANGED;
pdu->Length = ENCOMSP_ORDER_HEADER_SIZE + 6;
s = Stream_New(NULL, pdu->Length);
encomsp_write_header(s, (ENCOMSP_ORDER_HEADER*) pdu);
Stream_Write_UINT16(s, pdu->Flags); /* Flags (2 bytes) */
Stream_Write_UINT32(s, pdu->ParticipantId); /* ParticipantId (4 bytes) */
Stream_SealLength(s);
encomsp_virtual_channel_write(encomsp, s);
return 1;
}
int encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU pdu;
context = encomsp_get_client_interface(encomsp);
if (!context)
return -1;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
return -1;
if ((beg + header->Length) > end)
{
if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
return -1;
Stream_SetPosition(s, (beg + header->Length));
}
if (context->GraphicsStreamPaused)
{
return context->GraphicsStreamPaused(context, &pdu);
}
return 1;
}
int encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header)
{
int beg, end;
EncomspClientContext* context;
ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU pdu;
context = encomsp_get_client_interface(encomsp);
if (!context)
return -1;
beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER));
end = (int) Stream_GetPosition(s);
if ((beg + header->Length) < end)
return -1;
if ((beg + header->Length) > end)
{
if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
return -1;
Stream_SetPosition(s, (beg + header->Length));
}
if (context->GraphicsStreamResumed)
{
return context->GraphicsStreamResumed(context, &pdu);
}
return 1;
}
static int encomsp_process_receive(encomspPlugin* encomsp, wStream* s)
{
int status = 1;
ENCOMSP_ORDER_HEADER header;
while (Stream_GetRemainingLength(s) > 0)
{
if (encomsp_read_header(s, &header) < 0)
return -1;
//printf("EncomspReceive: Type: %d Length: %d\n", header.Type, header.Length);
switch (header.Type)
{
case ODTYPE_FILTER_STATE_UPDATED:
status = encomsp_recv_filter_updated_pdu(encomsp, s, &header);
break;
case ODTYPE_APP_REMOVED:
status = encomsp_recv_application_removed_pdu(encomsp, s, &header);
break;
case ODTYPE_APP_CREATED:
status = encomsp_recv_application_created_pdu(encomsp, s, &header);
break;
case ODTYPE_WND_REMOVED:
status = encomsp_recv_window_removed_pdu(encomsp, s, &header);
break;
case ODTYPE_WND_CREATED:
status = encomsp_recv_window_created_pdu(encomsp, s, &header);
break;
case ODTYPE_WND_SHOW:
status = encomsp_recv_show_window_pdu(encomsp, s, &header);
break;
case ODTYPE_PARTICIPANT_REMOVED:
status = encomsp_recv_participant_removed_pdu(encomsp, s, &header);
break;
case ODTYPE_PARTICIPANT_CREATED:
status = encomsp_recv_participant_created_pdu(encomsp, s, &header);
break;
case ODTYPE_PARTICIPANT_CTRL_CHANGED:
status = encomsp_recv_change_participant_control_level_pdu(encomsp, s, &header);
break;
case ODTYPE_GRAPHICS_STREAM_PAUSED:
status = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header);
break;
case ODTYPE_GRAPHICS_STREAM_RESUMED:
status = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header);
break;
default:
status = -1;
break;
}
if (status < 0)
return -1;
}
return status;
}
static void encomsp_process_connect(encomspPlugin* encomsp)
{
}
/****************************************************************************************/
static wListDictionary* g_InitHandles;
static wListDictionary* g_OpenHandles;
void encomsp_add_init_handle_data(void* pInitHandle, void* pUserData)
{
if (!g_InitHandles)
g_InitHandles = ListDictionary_New(TRUE);
ListDictionary_Add(g_InitHandles, pInitHandle, pUserData);
}
void* encomsp_get_init_handle_data(void* pInitHandle)
{
void* pUserData = NULL;
pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
return pUserData;
}
void encomsp_remove_init_handle_data(void* pInitHandle)
{
ListDictionary_Remove(g_InitHandles, pInitHandle);
}
void encomsp_add_open_handle_data(DWORD openHandle, void* pUserData)
{
void* pOpenHandle = (void*) (size_t) openHandle;
if (!g_OpenHandles)
g_OpenHandles = ListDictionary_New(TRUE);
ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData);
}
void* encomsp_get_open_handle_data(DWORD openHandle)
{
void* pUserData = NULL;
void* pOpenHandle = (void*) (size_t) openHandle;
pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
return pUserData;
}
void encomsp_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
}
int encomsp_send(encomspPlugin* encomsp, wStream* s)
{
UINT32 status = 0;
encomspPlugin* plugin = (encomspPlugin*) encomsp;
if (!plugin)
{
status = CHANNEL_RC_BAD_INIT_HANDLE;
}
else
{
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
}
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
fprintf(stderr, "encomsp_send: VirtualChannelWrite failed %d\n", status);
}
return status;
}
static void encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp,
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
wStream* data_in;
if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
{
return;
}
if (dataFlags & CHANNEL_FLAG_FIRST)
{
if (encomsp->data_in)
Stream_Free(encomsp->data_in, TRUE);
encomsp->data_in = Stream_New(NULL, totalLength);
}
data_in = encomsp->data_in;
Stream_EnsureRemainingCapacity(data_in, (int) dataLength);
Stream_Write(data_in, pData, dataLength);
if (dataFlags & CHANNEL_FLAG_LAST)
{
if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
{
fprintf(stderr, "encomsp_plugin_process_received: read error\n");
}
encomsp->data_in = NULL;
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(encomsp->MsgPipe->In, NULL, 0, (void*) data_in, NULL);
}
}
static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle, UINT event,
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
encomspPlugin* encomsp;
encomsp = (encomspPlugin*) encomsp_get_open_handle_data(openHandle);
if (!encomsp)
{
fprintf(stderr, "encomsp_virtual_channel_open_event: error no match\n");
return;
}
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength, totalLength, dataFlags);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
Stream_Free((wStream*) pData, TRUE);
break;
case CHANNEL_EVENT_USER:
break;
}
}
static void* encomsp_virtual_channel_client_thread(void* arg)
{
wStream* data;
wMessage message;
encomspPlugin* encomsp = (encomspPlugin*) arg;
encomsp_process_connect(encomsp);
while (1)
{
if (!MessageQueue_Wait(encomsp->MsgPipe->In))
break;
if (MessageQueue_Peek(encomsp->MsgPipe->In, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
{
data = (wStream*) message.wParam;
encomsp_process_receive(encomsp, data);
}
}
}
ExitThread(0);
return NULL;
}
static void encomsp_virtual_channel_event_connected(encomspPlugin* encomsp, LPVOID pData, UINT32 dataLength)
{
UINT32 status;
status = encomsp->channelEntryPoints.pVirtualChannelOpen(encomsp->InitHandle,
&encomsp->OpenHandle, encomsp->channelDef.name, encomsp_virtual_channel_open_event);
encomsp_add_open_handle_data(encomsp->OpenHandle, encomsp);
if (status != CHANNEL_RC_OK)
{
fprintf(stderr, "encomsp_virtual_channel_event_connected: open failed: status: %d\n", status);
return;
}
encomsp->MsgPipe = MessagePipe_New();
encomsp->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) encomsp_virtual_channel_client_thread, (void*) encomsp, 0, NULL);
}
static void encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
{
MessagePipe_PostQuit(encomsp->MsgPipe, 0);
WaitForSingleObject(encomsp->thread, INFINITE);
MessagePipe_Free(encomsp->MsgPipe);
CloseHandle(encomsp->thread);
encomsp->channelEntryPoints.pVirtualChannelClose(encomsp->OpenHandle);
if (encomsp->data_in)
{
Stream_Free(encomsp->data_in, TRUE);
encomsp->data_in = NULL;
}
encomsp_remove_open_handle_data(encomsp->OpenHandle);
encomsp_remove_init_handle_data(encomsp->InitHandle);
}
static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
{
encomspPlugin* encomsp;
encomsp = (encomspPlugin*) encomsp_get_init_handle_data(pInitHandle);
if (!encomsp)
{
fprintf(stderr, "encomsp_virtual_channel_init_event: error no match\n");
return;
}
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
encomsp_virtual_channel_event_connected(encomsp, pData, dataLength);
break;
case CHANNEL_EVENT_DISCONNECTED:
break;
case CHANNEL_EVENT_TERMINATED:
encomsp_virtual_channel_event_terminated(encomsp);
break;
}
}
/* encomsp is always built-in */
#define VirtualChannelEntry encomsp_VirtualChannelEntry
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
encomspPlugin* encomsp;
EncomspClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
encomsp = (encomspPlugin*) calloc(1, sizeof(encomspPlugin));
encomsp->channelDef.options =
CHANNEL_OPTION_INITIALIZED |
CHANNEL_OPTION_ENCRYPT_RDP |
CHANNEL_OPTION_COMPRESS_RDP |
CHANNEL_OPTION_SHOW_PROTOCOL;
strcpy(encomsp->channelDef.name, "encomsp");
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
{
context = (EncomspClientContext*) calloc(1, sizeof(EncomspClientContext));
context->handle = (void*) encomsp;
context->FilterUpdated = NULL;
context->ApplicationCreated = NULL;
context->ApplicationRemoved = NULL;
context->WindowCreated = NULL;
context->WindowRemoved = NULL;
context->ShowWindow = NULL;
context->ParticipantCreated = NULL;
context->ParticipantRemoved = NULL;
context->ChangeParticipantControlLevel = encomsp_send_change_participant_control_level_pdu;
context->GraphicsStreamPaused = NULL;
context->GraphicsStreamResumed = NULL;
*(pEntryPointsEx->ppInterface) = (void*) context;
}
CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
encomsp->channelEntryPoints.pVirtualChannelInit(&encomsp->InitHandle,
&encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, encomsp_virtual_channel_init_event);
encomsp->channelEntryPoints.pInterface = *(encomsp->channelEntryPoints.ppInterface);
encomsp->channelEntryPoints.ppInterface = &(encomsp->channelEntryPoints.pInterface);
encomsp_add_init_handle_data(encomsp->InitHandle, (void*) encomsp);
return 1;
}

View File

@ -0,0 +1,48 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Multiparty Virtual Channel
*
* Copyright 2014 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.
*/
#ifndef FREERDP_CHANNEL_ENCOMSP_CLIENT_MAIN_H
#define FREERDP_CHANNEL_ENCOMSP_CLIENT_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <freerdp/api.h>
#include <freerdp/svc.h>
#include <freerdp/addin.h>
#include <freerdp/client/encomsp.h>
struct encomsp_plugin
{
CHANNEL_DEF channelDef;
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
HANDLE thread;
wStream* data_in;
void* InitHandle;
DWORD OpenHandle;
wMessagePipe* MsgPipe;
};
typedef struct encomsp_plugin encomspPlugin;
#endif /* FREERDP_CHANNEL_ENCOMSP_CLIENT_MAIN_H */

View File

@ -0,0 +1,37 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 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.
define_channel_server("encomsp")
set(${MODULE_PREFIX}_SRCS
encomsp_main.c
encomsp_main.h)
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-crt)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -0,0 +1,157 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Multiparty Virtual Channel
*
* Copyright 2014 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include "encomsp_main.h"
static int encomsp_server_receive_pdu(EncomspServerContext* context, wStream* s)
{
return 0;
}
static void* encomsp_server_thread(void* arg)
{
wStream* s;
DWORD status;
DWORD nCount;
void* buffer;
HANDLE events[8];
HANDLE ChannelEvent;
DWORD BytesReturned;
EncomspServerContext* context;
context = (EncomspServerContext*) arg;
buffer = NULL;
BytesReturned = 0;
ChannelEvent = NULL;
s = Stream_New(NULL, 4096);
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
{
if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
}
nCount = 0;
events[nCount++] = ChannelEvent;
events[nCount++] = context->priv->StopEvent;
while (1)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
{
if (BytesReturned)
Stream_Seek(s, BytesReturned);
}
else
{
Stream_EnsureRemainingCapacity(s, BytesReturned);
}
if (0)
{
encomsp_server_receive_pdu(context, s);
}
}
Stream_Free(s, TRUE);
return NULL;
}
static int encomsp_server_start(EncomspServerContext* context)
{
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "encomsp");
if (!context->priv->ChannelHandle)
return -1;
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) encomsp_server_thread, (void*) context, 0, NULL);
return 0;
}
static int encomsp_server_stop(EncomspServerContext* context)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
return 0;
}
EncomspServerContext* encomsp_server_context_new(HANDLE vcm)
{
EncomspServerContext* context;
context = (EncomspServerContext*) calloc(1, sizeof(EncomspServerContext));
if (context)
{
context->vcm = vcm;
context->Start = encomsp_server_start;
context->Stop = encomsp_server_stop;
context->priv = (EncomspServerPrivate*) calloc(1, sizeof(EncomspServerPrivate));
if (context->priv)
{
}
}
return context;
}
void encomsp_server_context_free(EncomspServerContext* context)
{
if (context)
{
if (context->priv)
{
free(context->priv);
}
free(context);
}
}

View File

@ -0,0 +1,36 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Multiparty Virtual Channel
*
* Copyright 2014 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.
*/
#ifndef FREERDP_CHANNEL_SERVER_ENCOMSP_MAIN_H
#define FREERDP_CHANNEL_SERVER_ENCOMSP_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <freerdp/server/encomsp.h>
struct _encomsp_server_private
{
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
};
#endif /* FREERDP_CHANNEL_SERVER_ENCOMSP_MAIN_H */

View File

@ -460,6 +460,8 @@ static void* drive_hotplug_thread_func(void* arg)
tv.tv_sec = 1;
tv.tv_usec = 0;
handle_hotplug(rdpdr);
while ((rv = select(mfd+1, NULL, NULL, &rfds, &tv)) >= 0)
{
if (WaitForSingleObject(rdpdr->stopEvent, 0) == WAIT_OBJECT_0)

View File

@ -31,7 +31,7 @@
#include "rdpsnd_main.h"
static BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
{
int pos;
UINT16 i;
@ -187,49 +187,20 @@ out_free:
static void* rdpsnd_server_thread(void* arg)
{
wStream* s;
DWORD status;
DWORD nCount;
void* buffer;
BYTE msgType;
UINT16 BodySize;
DWORD nCount, status;
HANDLE events[8];
HANDLE ChannelEvent;
DWORD bytesReturned;
RdpsndServerContext* context;
BOOL doRun;
BOOL waitingHeader;
DWORD expectedBytes;
context = (RdpsndServerContext *)arg;
buffer = NULL;
bytesReturned = 0;
s = Stream_New(NULL, 4096);
if (!s)
return NULL;
if (!WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE)))
{
fprintf(stderr, "%s: error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)\n",
__FUNCTION__, bytesReturned);
return NULL;
}
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
nCount = 0;
events[nCount++] = ChannelEvent;
events[nCount++] = context->priv->channelEvent;
events[nCount++] = context->priv->StopEvent;
if (!rdpsnd_server_send_formats(context, s))
if (!rdpsnd_server_send_formats(context, context->priv->rdpsnd_pdu))
goto out;
doRun = TRUE;
waitingHeader = TRUE;
expectedBytes = 4;
while (doRun)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
@ -237,69 +208,17 @@ static void* rdpsnd_server_thread(void* arg)
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
break;
if (!WTSVirtualChannelRead(ChannelEvent, 0, (PCHAR)Stream_Pointer(s), expectedBytes, &bytesReturned))
{
fprintf(stderr, "%s: channel connection closed\n", __FUNCTION__);
if (!rdpsnd_server_handle_messages(context))
break;
}
expectedBytes -= bytesReturned;
Stream_Seek(s, bytesReturned);
if (expectedBytes)
continue;
Stream_SetPosition(s, 0);
if (waitingHeader)
{
/* header case */
Stream_Read_UINT8(s, msgType);
Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, BodySize);
expectedBytes = BodySize;
waitingHeader = FALSE;
Stream_SetPosition(s, 0);
Stream_EnsureCapacity(s, BodySize);
if (expectedBytes)
continue;
}
/* when here we have the header + the body */
switch (msgType)
{
case SNDC_WAVECONFIRM:
doRun = rdpsnd_server_recv_waveconfirm(context, s);
break;
case SNDC_QUALITYMODE:
doRun = rdpsnd_server_recv_quality_mode(context, s);
break;
case SNDC_FORMATS:
doRun = rdpsnd_server_recv_formats(context, s);
if (doRun)
{
IFCALL(context->Activated, context);
}
break;
default:
fprintf(stderr, "%s: UNKOWN MESSAGE TYPE!! (%#0X)\n\n", __FUNCTION__, msgType);
break;
}
expectedBytes = 4;
waitingHeader = TRUE;
Stream_SetPosition(s, 0);
}
out:
Stream_Free(s, TRUE);
return NULL;
}
static BOOL rdpsnd_server_initialize(RdpsndServerContext* context)
static BOOL rdpsnd_server_initialize(RdpsndServerContext* context, BOOL ownThread)
{
context->priv->ownThread = ownThread;
return context->Start(context) >= 0;
}
@ -546,22 +465,41 @@ static BOOL rdpsnd_server_close(RdpsndServerContext* context)
static int rdpsnd_server_start(RdpsndServerContext* context)
{
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpsnd");
if (!context->priv->ChannelHandle)
void *buffer = NULL;
DWORD bytesReturned;
RdpsndServerPrivate *priv = context->priv;
priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpsnd");
if (!priv->ChannelHandle)
return -1;
context->priv->rdpsnd_pdu = Stream_New(NULL, 4096);
if (!context->priv->rdpsnd_pdu)
if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE)))
{
fprintf(stderr, "%s: error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)\n",
__FUNCTION__, bytesReturned);
if (buffer)
WTSFreeMemory(buffer);
goto out_close;
}
CopyMemory(&priv->channelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
priv->rdpsnd_pdu = Stream_New(NULL, 4096);
if (!priv->rdpsnd_pdu)
goto out_close;
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!context->priv->StopEvent)
goto out_pdu;
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL);
if (!context->priv->Thread)
goto out_stopEvent;
if (priv->ownThread)
{
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!context->priv->StopEvent)
goto out_pdu;
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL);
if (!context->priv->Thread)
goto out_stopEvent;
}
return 0;
@ -579,12 +517,15 @@ out_close:
static int rdpsnd_server_stop(RdpsndServerContext* context)
{
if (context->priv->StopEvent)
if (context->priv->ownThread)
{
SetEvent(context->priv->StopEvent);
if (context->priv->StopEvent)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
}
}
return 0;
@ -593,8 +534,9 @@ static int rdpsnd_server_stop(RdpsndServerContext* context)
RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
{
RdpsndServerContext* context;
RdpsndServerPrivate *priv;
context = (RdpsndServerContext*) calloc(1, sizeof(RdpsndServerContext));
context = (RdpsndServerContext *)calloc(1, sizeof(RdpsndServerContext));
if (!context)
return NULL;
@ -610,16 +552,25 @@ RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm)
context->SetVolume = rdpsnd_server_set_volume;
context->Close = rdpsnd_server_close;
context->priv = (RdpsndServerPrivate*) calloc(1, sizeof(RdpsndServerPrivate));
if (!context->priv)
context->priv = priv = (RdpsndServerPrivate *)calloc(1, sizeof(RdpsndServerPrivate));
if (!priv)
goto out_free;
context->priv->dsp_context = freerdp_dsp_context_new();
if (!context->priv->dsp_context)
priv->dsp_context = freerdp_dsp_context_new();
if (!priv->dsp_context)
goto out_free_priv;
priv->input_stream = Stream_New(NULL, 4);
if (!priv->input_stream)
goto out_free_dsp;
priv->expectedBytes = 4;
priv->waitingHeader = TRUE;
priv->ownThread = TRUE;
return context;
out_free_dsp:
freerdp_dsp_context_free(priv->dsp_context);
out_free_priv:
free(context->priv);
out_free:
@ -627,6 +578,15 @@ out_free:
return NULL;
}
void rdpsnd_server_context_reset(RdpsndServerContext *context)
{
context->priv->expectedBytes = 4;
context->priv->waitingHeader = TRUE;
Stream_SetPosition(context->priv->input_stream, 0);
}
void rdpsnd_server_context_free(RdpsndServerContext* context)
{
if (!context->priv->StopEvent)
@ -652,3 +612,84 @@ void rdpsnd_server_context_free(RdpsndServerContext* context)
free(context);
}
HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext *context)
{
return context->priv->channelEvent;
}
BOOL rdpsnd_server_handle_messages(RdpsndServerContext *context)
{
DWORD bytesReturned;
BOOL ret;
RdpsndServerPrivate *priv = context->priv;
wStream *s = priv->input_stream;
if (!WTSVirtualChannelRead(priv->channelEvent, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned))
{
if (GetLastError() == ERROR_NO_DATA)
return TRUE;
fprintf(stderr, "%s: channel connection closed\n", __FUNCTION__);
return FALSE;
}
priv->expectedBytes -= bytesReturned;
Stream_Seek(s, bytesReturned);
if (priv->expectedBytes)
return TRUE;
Stream_SetPosition(s, 0);
if (priv->waitingHeader)
{
/* header case */
Stream_Read_UINT8(s, priv->msgType);
Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, priv->expectedBytes);
priv->waitingHeader = FALSE;
Stream_SetPosition(s, 0);
if (priv->expectedBytes)
{
Stream_EnsureCapacity(s, priv->expectedBytes);
return TRUE;
}
}
/* when here we have the header + the body */
#ifdef WITH_DEBUG_SND
fprintf(stderr, "%s: message type %d\n", __FUNCTION__, priv->msgType);
#endif
priv->expectedBytes = 4;
priv->waitingHeader = TRUE;
switch (priv->msgType)
{
case SNDC_WAVECONFIRM:
ret = rdpsnd_server_recv_waveconfirm(context, s);
break;
case SNDC_FORMATS:
ret = rdpsnd_server_recv_formats(context, s);
break;
case SNDC_QUALITYMODE:
ret = rdpsnd_server_recv_quality_mode(context, s);
Stream_SetPosition(s, 0); /* in case the Activated callback tries to treat some messages */
if (ret)
{
IFCALL(context->Activated, context);
}
break;
default:
fprintf(stderr, "%s: UNKOWN MESSAGE TYPE!! (%#0X)\n\n", __FUNCTION__, priv->msgType);
ret = FALSE;
break;
}
Stream_SetPosition(s, 0);
return ret;
}

View File

@ -31,10 +31,16 @@
struct _rdpsnd_server_private
{
BOOL ownThread;
HANDLE Thread;
HANDLE StopEvent;
HANDLE channelEvent;
void* ChannelHandle;
BOOL waitingHeader;
DWORD expectedBytes;
BYTE msgType;
wStream* input_stream;
wStream* rdpsnd_pdu;
BYTE* out_buffer;
int out_buffer_size;

View File

@ -0,0 +1,26 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 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.
define_channel("remdesk")
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -0,0 +1,12 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT ON)
define_channel_options(NAME "remdesk" TYPE "static"
DESCRIPTION "Remote Assistance Virtual Channel Extension"
SPECIFICATIONS "[MS-RA]"
DEFAULT ${OPTION_DEFAULT})
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})

View File

@ -0,0 +1,40 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 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.
define_channel_client("remdesk")
set(${MODULE_PREFIX}_SRCS
remdesk_main.c
remdesk_main.h)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-common)
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-crt)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -0,0 +1,804 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Remote Assistance Virtual Channel
*
* Copyright 2014 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <freerdp/assistance.h>
#include <freerdp/client/remdesk.h>
#include "remdesk_main.h"
RemdeskClientContext* remdesk_get_client_interface(remdeskPlugin* remdesk)
{
RemdeskClientContext* pInterface;
pInterface = (RemdeskClientContext*) remdesk->channelEntryPoints.pInterface;
return pInterface;
}
int remdesk_virtual_channel_write(remdeskPlugin* remdesk, wStream* s)
{
UINT32 status = 0;
if (!remdesk)
return -1;
status = remdesk->channelEntryPoints.pVirtualChannelWrite(remdesk->OpenHandle,
Stream_Buffer(s), (UINT32) Stream_Length(s), s);
if (status != CHANNEL_RC_OK)
{
fprintf(stderr, "remdesk_virtual_channel_write: VirtualChannelWrite failed %d\n", status);
return -1;
}
return 1;
}
int remdesk_generate_expert_blob(remdeskPlugin* remdesk)
{
char* name;
char* pass;
char* password;
rdpSettings* settings = remdesk->settings;
if (remdesk->ExpertBlob)
return 1;
if (settings->RemoteAssistancePassword)
password = settings->RemoteAssistancePassword;
else
password = settings->Password;
if (!password)
return -1;
name = settings->Username;
if (!name)
name = "Expert";
remdesk->EncryptedPassStub = freerdp_assistance_encrypt_pass_stub(password,
settings->RemoteAssistancePassStub, &(remdesk->EncryptedPassStubSize));
if (!remdesk->EncryptedPassStub)
return -1;
pass = freerdp_assistance_bin_to_hex_string(remdesk->EncryptedPassStub, remdesk->EncryptedPassStubSize);
if (!pass)
return -1;
remdesk->ExpertBlob = freerdp_assistance_construct_expert_blob(name, pass);
if (!remdesk->ExpertBlob)
return -1;
return 1;
}
int remdesk_read_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header)
{
int status;
UINT32 ChannelNameLen;
char* pChannelName = NULL;
if (Stream_GetRemainingLength(s) < 8)
return -1;
Stream_Read_UINT32(s, ChannelNameLen); /* ChannelNameLen (4 bytes) */
Stream_Read_UINT32(s, header->DataLength); /* DataLen (4 bytes) */
if (ChannelNameLen > 64)
return -1;
if ((ChannelNameLen % 2) != 0)
return -1;
if (Stream_GetRemainingLength(s) < ChannelNameLen)
return -1;
ZeroMemory(header->ChannelName, sizeof(header->ChannelName));
pChannelName = (char*) header->ChannelName;
status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
ChannelNameLen / 2, &pChannelName, 32, NULL, NULL);
Stream_Seek(s, ChannelNameLen);
if (status <= 0)
return -1;
return 1;
}
int remdesk_write_channel_header(wStream* s, REMDESK_CHANNEL_HEADER* header)
{
int index;
UINT32 ChannelNameLen;
WCHAR ChannelNameW[32];
ZeroMemory(ChannelNameW, sizeof(ChannelNameW));
for (index = 0; index < 32; index++)
{
ChannelNameW[index] = (WCHAR) header->ChannelName[index];
}
ChannelNameLen = (strlen(header->ChannelName) + 1) * 2;
Stream_Write_UINT32(s, ChannelNameLen); /* ChannelNameLen (4 bytes) */
Stream_Write_UINT32(s, header->DataLength); /* DataLen (4 bytes) */
Stream_Write(s, ChannelNameW, ChannelNameLen); /* ChannelName (variable) */
return 1;
}
int remdesk_write_ctl_header(wStream* s, REMDESK_CTL_HEADER* ctlHeader)
{
remdesk_write_channel_header(s, (REMDESK_CHANNEL_HEADER*) ctlHeader);
Stream_Write_UINT32(s, ctlHeader->msgType); /* msgType (4 bytes) */
return 1;
}
int remdesk_prepare_ctl_header(REMDESK_CTL_HEADER* ctlHeader, UINT32 msgType, UINT32 msgSize)
{
ctlHeader->msgType = msgType;
strcpy(ctlHeader->ChannelName, REMDESK_CHANNEL_CTL_NAME);
ctlHeader->DataLength = 4 + msgSize;
return 1;
}
int remdesk_recv_ctl_server_announce_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
{
return 1;
}
int remdesk_recv_ctl_version_info_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
{
UINT32 versionMajor;
UINT32 versionMinor;
if (Stream_GetRemainingLength(s) < 8)
return -1;
Stream_Read_UINT32(s, versionMajor); /* versionMajor (4 bytes) */
Stream_Read_UINT32(s, versionMinor); /* versionMinor (4 bytes) */
return 1;
}
int remdesk_send_ctl_version_info_pdu(remdeskPlugin* remdesk)
{
wStream* s;
REMDESK_CTL_VERSION_INFO_PDU pdu;
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERSIONINFO, 8);
pdu.versionMajor = 1;
pdu.versionMinor = 2;
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
Stream_Write_UINT32(s, pdu.versionMajor); /* versionMajor (4 bytes) */
Stream_Write_UINT32(s, pdu.versionMinor); /* versionMinor (4 bytes) */
Stream_SealLength(s);
remdesk_virtual_channel_write(remdesk, s);
return 1;
}
int remdesk_recv_result_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header, UINT32 *pResult)
{
UINT32 result;
if (Stream_GetRemainingLength(s) < 4)
return -1;
Stream_Read_UINT32(s, result); /* result (4 bytes) */
*pResult = result;
//printf("RemdeskRecvResult: 0x%04X\n", result);
return 1;
}
int remdesk_send_ctl_authenticate_pdu(remdeskPlugin* remdesk)
{
int status;
wStream* s;
int cbExpertBlobW = 0;
WCHAR* expertBlobW = NULL;
int cbRaConnectionStringW = 0;
WCHAR* raConnectionStringW = NULL;
REMDESK_CTL_AUTHENTICATE_PDU pdu;
status = remdesk_generate_expert_blob(remdesk);
if (status < 0)
return -1;
pdu.expertBlob = remdesk->ExpertBlob;
pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket;
status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1, &raConnectionStringW, 0);
if (status <= 0)
return -1;
cbRaConnectionStringW = status * 2;
status = ConvertToUnicode(CP_UTF8, 0, pdu.expertBlob, -1, &expertBlobW, 0);
if (status <= 0)
return -1;
cbExpertBlobW = status * 2;
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_AUTHENTICATE,
cbRaConnectionStringW + cbExpertBlobW);
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
Stream_Write(s, (BYTE*) raConnectionStringW, cbRaConnectionStringW);
Stream_Write(s, (BYTE*) expertBlobW, cbExpertBlobW);
Stream_SealLength(s);
remdesk_virtual_channel_write(remdesk, s);
free(raConnectionStringW);
free(expertBlobW);
return 1;
}
int remdesk_send_ctl_remote_control_desktop_pdu(remdeskPlugin* remdesk)
{
int status;
wStream* s;
int cbRaConnectionStringW = 0;
WCHAR* raConnectionStringW = NULL;
REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU pdu;
pdu.raConnectionString = remdesk->settings->RemoteAssistanceRCTicket;
status = ConvertToUnicode(CP_UTF8, 0, pdu.raConnectionString, -1, &raConnectionStringW, 0);
if (status <= 0)
return -1;
cbRaConnectionStringW = status * 2;
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_REMOTE_CONTROL_DESKTOP, cbRaConnectionStringW);
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
Stream_Write(s, (BYTE*) raConnectionStringW, cbRaConnectionStringW);
Stream_SealLength(s);
remdesk_virtual_channel_write(remdesk, s);
free(raConnectionStringW);
return 1;
}
int remdesk_send_ctl_verify_password_pdu(remdeskPlugin* remdesk)
{
int status;
wStream* s;
int cbExpertBlobW = 0;
WCHAR* expertBlobW = NULL;
REMDESK_CTL_VERIFY_PASSWORD_PDU pdu;
status = remdesk_generate_expert_blob(remdesk);
if (status < 0)
return -1;
pdu.expertBlob = remdesk->ExpertBlob;
status = ConvertToUnicode(CP_UTF8, 0, pdu.expertBlob, -1, &expertBlobW, 0);
if (status <= 0)
return -1;
cbExpertBlobW = status * 2;
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_VERIFY_PASSWORD, cbExpertBlobW);
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
Stream_Write(s, (BYTE*) expertBlobW, cbExpertBlobW);
Stream_SealLength(s);
remdesk_virtual_channel_write(remdesk, s);
free(expertBlobW);
return 1;
}
int remdesk_send_ctl_expert_on_vista_pdu(remdeskPlugin* remdesk)
{
int status;
wStream* s;
REMDESK_CTL_EXPERT_ON_VISTA_PDU pdu;
status = remdesk_generate_expert_blob(remdesk);
if (status < 0)
return -1;
pdu.EncryptedPasswordLength = remdesk->EncryptedPassStubSize;
pdu.EncryptedPassword = remdesk->EncryptedPassStub;
remdesk_prepare_ctl_header(&(pdu.ctlHeader), REMDESK_CTL_EXPERT_ON_VISTA,
pdu.EncryptedPasswordLength);
s = Stream_New(NULL, REMDESK_CHANNEL_CTL_SIZE + pdu.ctlHeader.DataLength);
remdesk_write_ctl_header(s, &(pdu.ctlHeader));
Stream_Write(s, pdu.EncryptedPassword, pdu.EncryptedPasswordLength);
Stream_SealLength(s);
remdesk_virtual_channel_write(remdesk, s);
return 1;
}
int remdesk_recv_ctl_pdu(remdeskPlugin* remdesk, wStream* s, REMDESK_CHANNEL_HEADER* header)
{
int status = 1;
UINT32 msgType = 0;
UINT32 result = 0;
if (Stream_GetRemainingLength(s) < 4)
return -1;
Stream_Read_UINT32(s, msgType); /* msgType (4 bytes) */
//printf("msgType: %d\n", msgType);
switch (msgType)
{
case REMDESK_CTL_REMOTE_CONTROL_DESKTOP:
break;
case REMDESK_CTL_RESULT:
status = remdesk_recv_result_pdu(remdesk, s, header, &result);
break;
case REMDESK_CTL_AUTHENTICATE:
break;
case REMDESK_CTL_SERVER_ANNOUNCE:
status = remdesk_recv_ctl_server_announce_pdu(remdesk, s, header);
break;
case REMDESK_CTL_DISCONNECT:
break;
case REMDESK_CTL_VERSIONINFO:
status = remdesk_recv_ctl_version_info_pdu(remdesk, s, header);
if (remdesk->Version == 1)
{
if (status >= 0)
status = remdesk_send_ctl_version_info_pdu(remdesk);
if (status >= 0)
status = remdesk_send_ctl_authenticate_pdu(remdesk);
if (status >= 0)
status = remdesk_send_ctl_remote_control_desktop_pdu(remdesk);
}
else if (remdesk->Version == 2)
{
if (status >= 0)
status = remdesk_send_ctl_expert_on_vista_pdu(remdesk);
if (status >= 0)
status = remdesk_send_ctl_verify_password_pdu(remdesk);
}
break;
case REMDESK_CTL_ISCONNECTED:
break;
case REMDESK_CTL_VERIFY_PASSWORD:
break;
case REMDESK_CTL_EXPERT_ON_VISTA:
break;
case REMDESK_CTL_RANOVICE_NAME:
break;
case REMDESK_CTL_RAEXPERT_NAME:
break;
case REMDESK_CTL_TOKEN:
break;
default:
fprintf(stderr, "remdesk_recv_control_pdu: unknown msgType: %d\n", msgType);
status = -1;
break;
}
return status;
}
int remdesk_process_receive(remdeskPlugin* remdesk, wStream* s)
{
int status = 1;
REMDESK_CHANNEL_HEADER header;
#if 0
printf("RemdeskReceive: %d\n", Stream_GetRemainingLength(s));
winpr_HexDump(Stream_Pointer(s), Stream_GetRemainingLength(s));
#endif
remdesk_read_channel_header(s, &header);
if (strcmp(header.ChannelName, "RC_CTL") == 0)
{
status = remdesk_recv_ctl_pdu(remdesk, s, &header);
}
else if (strcmp(header.ChannelName, "70") == 0)
{
}
else if (strcmp(header.ChannelName, "71") == 0)
{
}
else if (strcmp(header.ChannelName, ".") == 0)
{
}
else if (strcmp(header.ChannelName, "1000.") == 0)
{
}
else if (strcmp(header.ChannelName, "RA_FX") == 0)
{
}
else
{
}
return status;
}
static void remdesk_process_connect(remdeskPlugin* remdesk)
{
remdesk->settings = (rdpSettings*) remdesk->channelEntryPoints.pExtendedData;
}
/****************************************************************************************/
static wListDictionary* g_InitHandles;
static wListDictionary* g_OpenHandles;
void remdesk_add_init_handle_data(void* pInitHandle, void* pUserData)
{
if (!g_InitHandles)
g_InitHandles = ListDictionary_New(TRUE);
ListDictionary_Add(g_InitHandles, pInitHandle, pUserData);
}
void* remdesk_get_init_handle_data(void* pInitHandle)
{
void* pUserData = NULL;
pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
return pUserData;
}
void remdesk_remove_init_handle_data(void* pInitHandle)
{
ListDictionary_Remove(g_InitHandles, pInitHandle);
}
void remdesk_add_open_handle_data(DWORD openHandle, void* pUserData)
{
void* pOpenHandle = (void*) (size_t) openHandle;
if (!g_OpenHandles)
g_OpenHandles = ListDictionary_New(TRUE);
ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData);
}
void* remdesk_get_open_handle_data(DWORD openHandle)
{
void* pUserData = NULL;
void* pOpenHandle = (void*) (size_t) openHandle;
pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
return pUserData;
}
void remdesk_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
}
int remdesk_send(remdeskPlugin* remdesk, wStream* s)
{
UINT32 status = 0;
remdeskPlugin* plugin = (remdeskPlugin*) remdesk;
if (!plugin)
{
status = CHANNEL_RC_BAD_INIT_HANDLE;
}
else
{
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s);
}
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
fprintf(stderr, "remdesk_send: VirtualChannelWrite failed %d\n", status);
}
return status;
}
static void remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk,
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
wStream* data_in;
if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
{
return;
}
if (dataFlags & CHANNEL_FLAG_FIRST)
{
if (remdesk->data_in)
Stream_Free(remdesk->data_in, TRUE);
remdesk->data_in = Stream_New(NULL, totalLength);
}
data_in = remdesk->data_in;
Stream_EnsureRemainingCapacity(data_in, (int) dataLength);
Stream_Write(data_in, pData, dataLength);
if (dataFlags & CHANNEL_FLAG_LAST)
{
if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
{
fprintf(stderr, "remdesk_plugin_process_received: read error\n");
}
remdesk->data_in = NULL;
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(remdesk->MsgPipe->In, NULL, 0, (void*) data_in, NULL);
}
}
static VOID VCAPITYPE remdesk_virtual_channel_open_event(DWORD openHandle, UINT event,
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
remdeskPlugin* remdesk;
remdesk = (remdeskPlugin*) remdesk_get_open_handle_data(openHandle);
if (!remdesk)
{
fprintf(stderr, "remdesk_virtual_channel_open_event: error no match\n");
return;
}
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
remdesk_virtual_channel_event_data_received(remdesk, pData, dataLength, totalLength, dataFlags);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
Stream_Free((wStream*) pData, TRUE);
break;
case CHANNEL_EVENT_USER:
break;
}
}
static void* remdesk_virtual_channel_client_thread(void* arg)
{
wStream* data;
wMessage message;
remdeskPlugin* remdesk = (remdeskPlugin*) arg;
remdesk_process_connect(remdesk);
while (1)
{
if (!MessageQueue_Wait(remdesk->MsgPipe->In))
break;
if (MessageQueue_Peek(remdesk->MsgPipe->In, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
{
data = (wStream*) message.wParam;
remdesk_process_receive(remdesk, data);
}
}
}
ExitThread(0);
return NULL;
}
static void remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk, LPVOID pData, UINT32 dataLength)
{
UINT32 status;
status = remdesk->channelEntryPoints.pVirtualChannelOpen(remdesk->InitHandle,
&remdesk->OpenHandle, remdesk->channelDef.name, remdesk_virtual_channel_open_event);
remdesk_add_open_handle_data(remdesk->OpenHandle, remdesk);
if (status != CHANNEL_RC_OK)
{
fprintf(stderr, "remdesk_virtual_channel_event_connected: open failed: status: %d\n", status);
return;
}
remdesk->MsgPipe = MessagePipe_New();
remdesk->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) remdesk_virtual_channel_client_thread, (void*) remdesk, 0, NULL);
}
static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk)
{
MessagePipe_PostQuit(remdesk->MsgPipe, 0);
WaitForSingleObject(remdesk->thread, INFINITE);
MessagePipe_Free(remdesk->MsgPipe);
CloseHandle(remdesk->thread);
remdesk->channelEntryPoints.pVirtualChannelClose(remdesk->OpenHandle);
if (remdesk->data_in)
{
Stream_Free(remdesk->data_in, TRUE);
remdesk->data_in = NULL;
}
remdesk_remove_open_handle_data(remdesk->OpenHandle);
remdesk_remove_init_handle_data(remdesk->InitHandle);
}
static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
{
remdeskPlugin* remdesk;
remdesk = (remdeskPlugin*) remdesk_get_init_handle_data(pInitHandle);
if (!remdesk)
{
fprintf(stderr, "remdesk_virtual_channel_init_event: error no match\n");
return;
}
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
remdesk_virtual_channel_event_connected(remdesk, pData, dataLength);
break;
case CHANNEL_EVENT_DISCONNECTED:
break;
case CHANNEL_EVENT_TERMINATED:
remdesk_virtual_channel_event_terminated(remdesk);
break;
}
}
/* remdesk is always built-in */
#define VirtualChannelEntry remdesk_VirtualChannelEntry
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
remdeskPlugin* remdesk;
RemdeskClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
remdesk = (remdeskPlugin*) calloc(1, sizeof(remdeskPlugin));
if (!remdesk)
return FALSE;
remdesk->channelDef.options =
CHANNEL_OPTION_INITIALIZED |
CHANNEL_OPTION_ENCRYPT_RDP |
CHANNEL_OPTION_COMPRESS_RDP |
CHANNEL_OPTION_SHOW_PROTOCOL;
strcpy(remdesk->channelDef.name, "remdesk");
remdesk->Version = 2;
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) &&
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
{
context = (RemdeskClientContext*) calloc(1, sizeof(RemdeskClientContext));
context->handle = (void*) remdesk;
*(pEntryPointsEx->ppInterface) = (void*) context;
}
CopyMemory(&(remdesk->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
remdesk->channelEntryPoints.pVirtualChannelInit(&remdesk->InitHandle,
&remdesk->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, remdesk_virtual_channel_init_event);
remdesk->channelEntryPoints.pInterface = *(remdesk->channelEntryPoints.ppInterface);
remdesk->channelEntryPoints.ppInterface = &(remdesk->channelEntryPoints.pInterface);
remdesk_add_init_handle_data(remdesk->InitHandle, (void*) remdesk);
return 1;
}

View File

@ -0,0 +1,55 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Remote Assistance Virtual Channel
*
* Copyright 2014 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.
*/
#ifndef FREERDP_CHANNEL_REMDESK_CLIENT_MAIN_H
#define FREERDP_CHANNEL_REMDESK_CLIENT_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <freerdp/api.h>
#include <freerdp/svc.h>
#include <freerdp/addin.h>
#include <freerdp/settings.h>
#include <freerdp/client/remdesk.h>
struct remdesk_plugin
{
CHANNEL_DEF channelDef;
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
HANDLE thread;
wStream* data_in;
void* InitHandle;
DWORD OpenHandle;
wMessagePipe* MsgPipe;
rdpSettings* settings;
UINT32 Version;
char* ExpertBlob;
BYTE* EncryptedPassStub;
int EncryptedPassStubSize;
};
typedef struct remdesk_plugin remdeskPlugin;
#endif /* FREERDP_CHANNEL_REMDESK_CLIENT_MAIN_H */

View File

@ -0,0 +1,37 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 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.
define_channel_server("remdesk")
set(${MODULE_PREFIX}_SRCS
remdesk_main.c
remdesk_main.h)
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-crt)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -0,0 +1,157 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Remote Assistance Virtual Channel
*
* Copyright 2014 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include "remdesk_main.h"
static int remdesk_server_receive_pdu(RemdeskServerContext* context, wStream* s)
{
return 0;
}
static void* remdesk_server_thread(void* arg)
{
wStream* s;
DWORD status;
DWORD nCount;
void* buffer;
HANDLE events[8];
HANDLE ChannelEvent;
DWORD BytesReturned;
RemdeskServerContext* context;
context = (RemdeskServerContext*) arg;
buffer = NULL;
BytesReturned = 0;
ChannelEvent = NULL;
s = Stream_New(NULL, 4096);
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
{
if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
}
nCount = 0;
events[nCount++] = ChannelEvent;
events[nCount++] = context->priv->StopEvent;
while (1)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
{
if (BytesReturned)
Stream_Seek(s, BytesReturned);
}
else
{
Stream_EnsureRemainingCapacity(s, BytesReturned);
}
if (0)
{
remdesk_server_receive_pdu(context, s);
}
}
Stream_Free(s, TRUE);
return NULL;
}
static int remdesk_server_start(RemdeskServerContext* context)
{
context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "remdesk");
if (!context->priv->ChannelHandle)
return -1;
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) remdesk_server_thread, (void*) context, 0, NULL);
return 0;
}
static int remdesk_server_stop(RemdeskServerContext* context)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
return 0;
}
RemdeskServerContext* remdesk_server_context_new(HANDLE vcm)
{
RemdeskServerContext* context;
context = (RemdeskServerContext*) calloc(1, sizeof(RemdeskServerContext));
if (context)
{
context->vcm = vcm;
context->Start = remdesk_server_start;
context->Stop = remdesk_server_stop;
context->priv = (RemdeskServerPrivate*) calloc(1, sizeof(RemdeskServerPrivate));
if (context->priv)
{
}
}
return context;
}
void remdesk_server_context_free(RemdeskServerContext* context)
{
if (context)
{
if (context->priv)
{
free(context->priv);
}
free(context);
}
}

View File

@ -0,0 +1,37 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Remote Assistance Virtual Channel
*
* Copyright 2014 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.
*/
#ifndef FREERDP_CHANNEL_SERVER_REMDESK_MAIN_H
#define FREERDP_CHANNEL_SERVER_REMDESK_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <freerdp/server/remdesk.h>
struct _remdesk_server_private
{
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
};
#endif /* FREERDP_CHANNEL_SERVER_REMDESK_MAIN_H */

View File

@ -388,8 +388,9 @@ static UINT32 smartcard_GetStatusChangeA_Call(SMARTCARD_DEVICE* smartcard, SMART
status = ret.ReturnCode = SCardGetStatusChangeA(operation->hContext, call->dwTimeOut, call->rgReaderStates, call->cReaders);
if (status && (status != SCARD_E_TIMEOUT) && (status != SCARD_E_CANCELLED))
return status;
if (status && (status != SCARD_E_TIMEOUT) && (status != SCARD_E_CANCELLED)){
call->cReaders=0;
}
ret.cReaders = call->cReaders;
ret.rgReaderStates = (ReaderState_Return*) calloc(ret.cReaders, sizeof(ReaderState_Return));
@ -453,8 +454,9 @@ static UINT32 smartcard_GetStatusChangeW_Call(SMARTCARD_DEVICE* smartcard, SMART
status = ret.ReturnCode = SCardGetStatusChangeW(operation->hContext, call->dwTimeOut, call->rgReaderStates, call->cReaders);
if (status && (status != SCARD_E_TIMEOUT) && (status != SCARD_E_CANCELLED))
return status;
if (status && (status != SCARD_E_TIMEOUT) && (status != SCARD_E_CANCELLED)){
call->cReaders=0;
}
ret.cReaders = call->cReaders;
ret.rgReaderStates = (ReaderState_Return*) calloc(ret.cReaders, sizeof(ReaderState_Return));

View File

@ -329,6 +329,7 @@ static int tsmf_on_new_channel_connection(IWTSListenerCallback *pListenerCallbac
ZeroMemory(callback, sizeof(TSMF_CHANNEL_CALLBACK));
callback->iface.OnDataReceived = tsmf_on_data_received;
callback->iface.OnClose = tsmf_on_close;
callback->iface.OnOpen = NULL;
callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel;

View File

@ -40,6 +40,10 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven
{
xf_graphics_pipeline_init(xfc, (RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
{
xf_encomsp_init(xfc, (EncomspClientContext*) e->pInterface);
}
}
void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e)
@ -54,4 +58,8 @@ void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnect
{
xf_graphics_pipeline_uninit(xfc, (RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
{
xf_encomsp_uninit(xfc, (EncomspClientContext*) e->pInterface);
}
}

View File

@ -24,6 +24,7 @@
#include <freerdp/client/channels.h>
#include <freerdp/client/rdpei.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/client/encomsp.h>
int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface);
int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface);

View File

@ -468,7 +468,7 @@ void xf_create_window(xfContext *xfc)
}
}
void xf_toggle_fullscreen(xfContext *xfc)
void xf_toggle_fullscreen(xfContext* xfc)
{
Pixmap contents = 0;
WindowStateChangeEventArgs e;
@ -486,6 +486,53 @@ void xf_toggle_fullscreen(xfContext *xfc)
PubSub_OnWindowStateChange(((rdpContext *) xfc)->pubSub, xfc, &e);
}
void xf_toggle_control(xfContext* xfc)
{
EncomspClientContext* encomsp;
ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu;
encomsp = xfc->encomsp;
if (!encomsp)
return;
pdu.ParticipantId = 0;
pdu.Flags = ENCOMSP_REQUEST_VIEW;
if (!xfc->controlToggle)
pdu.Flags |= ENCOMSP_REQUEST_INTERACT;
encomsp->ChangeParticipantControlLevel(encomsp, &pdu);
xfc->controlToggle = !xfc->controlToggle;
}
int xf_encomsp_participant_created(EncomspClientContext* context, ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated)
{
#if 0
xfContext* xfc = (xfContext*) context->custom;
printf("ParticipantCreated: ParticipantId: %d GroupId: %d Flags: 0x%04X xfc: %p\n",
(int) participantCreated->ParticipantId, (int) participantCreated->GroupId,
(int) participantCreated->Flags, xfc);
#endif
return 1;
}
void xf_encomsp_init(xfContext* xfc, EncomspClientContext* encomsp)
{
xfc->encomsp = encomsp;
encomsp->custom = (void*) xfc;
encomsp->ParticipantCreated = xf_encomsp_participant_created;
}
void xf_encomsp_uninit(xfContext* xfc, EncomspClientContext* encomsp)
{
xfc->encomsp = NULL;
}
void xf_lock_x11(xfContext *xfc, BOOL display)
{
if(!xfc->UseXThreads)

View File

@ -415,6 +415,16 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym)
}
}
if ((keysym == XK_c) || (keysym == XK_C))
{
if (mod.Ctrl && mod.Alt)
{
/* Ctrl-Alt-C: toggle control */
xf_toggle_control(xfc);
return TRUE;
}
}
if (keysym == XK_period)
{
if (mod.Ctrl && mod.Alt)

View File

@ -137,6 +137,7 @@ struct xf_context
BOOL mouse_active;
BOOL suppress_output;
BOOL fullscreen_toggle;
BOOL controlToggle;
UINT32 KeyboardLayout;
BOOL KeyboardState[256];
XModifierKeymap* modifierMap;
@ -182,12 +183,17 @@ struct xf_context
/* Channels */
RdpeiClientContext* rdpei;
RdpgfxClientContext* gfx;
EncomspClientContext* encomsp;
};
void xf_create_window(xfContext* xfc);
void xf_toggle_fullscreen(xfContext* xfc);
void xf_toggle_control(xfContext* xfc);
BOOL xf_post_connect(freerdp* instance);
void xf_encomsp_init(xfContext* xfc, EncomspClientContext* encomsp);
void xf_encomsp_uninit(xfContext* xfc, EncomspClientContext* encomsp);
enum XF_EXIT_CODE
{
/* section 0-15: protocol-independent codes */

View File

@ -52,6 +52,9 @@ set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVER
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
${FREERDP_CHANNELS_CLIENT_LIBS})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES})
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-core)
@ -60,8 +63,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHI
MODULE winpr
MODULES winpr-crt winpr-utils)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries EXPORT FreeRDPTargets)
@ -71,4 +72,5 @@ set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Common")
if(BUILD_TESTING)
add_subdirectory(test)
endif()
export_complex_library(LIBNAME ${MODULE_NAME})

View File

@ -24,6 +24,7 @@
#include <freerdp/client.h>
#include <freerdp/addin.h>
#include <freerdp/assistance.h>
#include <freerdp/client/file.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/client/channels.h>
@ -118,6 +119,11 @@ int freerdp_client_settings_parse_command_line(rdpSettings* settings, int argc,
status = freerdp_client_settings_parse_connection_file(settings, settings->ConnectionFile);
}
if (settings->AssistanceFile)
{
status = freerdp_client_settings_parse_assistance_file(settings, settings->AssistanceFile);
}
return status;
}
@ -167,3 +173,28 @@ int freerdp_client_settings_write_connection_file(const rdpSettings* settings, c
return 0;
}
int freerdp_client_settings_parse_assistance_file(rdpSettings* settings, const char* filename)
{
int status;
rdpAssistanceFile* file;
file = freerdp_assistance_file_new();
if (!file)
return -1;
status = freerdp_assistance_parse_file(file, filename);
if (status < 0)
return -1;
status = freerdp_client_populate_settings_from_assistance_file(file, settings);
if (status < 0)
return -1;
freerdp_assistance_file_free(file);
return 0;
}

View File

@ -156,6 +156,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "print-reconnect-cookie", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Print base64 reconnect cookie after connecting" },
{ "heartbeat", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support heartbeat PDUs" },
{ "multitransport", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support multitransport protocol" },
{ "assistance", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Remote assistance password" },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
@ -284,6 +285,17 @@ int freerdp_client_command_line_pre_filter(void* context, int index, int argc, L
return 1;
}
}
if (length > 13)
{
if (_stricmp(&(argv[index])[length - 13], ".msrcIncident") == 0)
{
settings = (rdpSettings*) context;
settings->AssistanceFile = _strdup(argv[index]);
return 1;
}
}
}
return 0;
@ -1848,6 +1860,11 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
{
settings->PrintReconnectCookie = arg->Value ? TRUE : FALSE;
}
CommandLineSwitchCase(arg, "assistance")
{
settings->RemoteAssistanceMode = TRUE;
settings->RemoteAssistancePassword = _strdup(arg->Value);
}
CommandLineSwitchDefault(arg)
{
}
@ -2026,6 +2043,12 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings)
}
}
if (settings->RemoteAssistanceMode)
{
freerdp_client_load_static_channel_addin(channels, settings, "encomsp", settings);
freerdp_client_load_static_channel_addin(channels, settings, "remdesk", settings);
}
for (index = 0; index < settings->StaticChannelCount; index++)
{
args = settings->StaticChannelArray[index];

View File

@ -28,11 +28,10 @@ find_library(Gobject_LIBRARY
PATHS ${Glib_PKGCONF_LIBRARY_DIRS} ${GLIB_ROOT_DIR}
)
# Glib-related libraries also use a separate config header, which is in lib dir
# Glib-related libraries also use a separate config header, which is relative to lib dir
find_path(GlibConfig_INCLUDE_DIR
NAMES glibconfig.h
PATHS ${Glib_PKGCONF_INCLUDE_DIRS} /usr ${GLIB_ROOT_DIR}
PATH_SUFFIXES lib/glib-2.0/include glib-2.0/include
PATHS ${Glib_PKGCONF_INCLUDE_DIRS} ${GLIB_ROOT_DIR}
)
# Set the include dir variables and the libraries and let libfind_process do the rest.

View File

@ -0,0 +1,79 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Remote Assistance
*
* Copyright 2014 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.
*/
#ifndef FREERDP_REMOTE_ASSISTANCE_H
#define FREERDP_REMOTE_ASSISTANCE_H
#include <freerdp/api.h>
#include <freerdp/freerdp.h>
struct rdp_assistance_file
{
UINT32 Type;
char* Username;
char* LHTicket;
char* RCTicket;
char* PassStub;
UINT32 DtStart;
UINT32 DtLength;
BOOL LowSpeed;
BOOL RCTicketEncrypted;
char* ConnectionString1;
char* ConnectionString2;
BYTE* EncryptedPassStub;
int EncryptedPassStubLength;
BYTE* EncryptedLHTicket;
int EncryptedLHTicketLength;
char* MachineAddress;
UINT32 MachinePort;
char* RASessionId;
char* RASpecificParams;
};
typedef struct rdp_assistance_file rdpAssistanceFile;
#ifdef __cplusplus
extern "C" {
#endif
FREERDP_API BYTE* freerdp_assistance_hex_string_to_bin(const char* str, int* size);
FREERDP_API char* freerdp_assistance_bin_to_hex_string(const BYTE* data, int size);
FREERDP_API char* freerdp_assistance_construct_expert_blob(const char* name, const char* pass);
FREERDP_API BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub, int* pEncryptedSize);
FREERDP_API int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* buffer, size_t size);
FREERDP_API int freerdp_assistance_parse_file(rdpAssistanceFile* file, const char* name);
FREERDP_API int freerdp_assistance_decrypt(rdpAssistanceFile* file, const char* password);
FREERDP_API int freerdp_client_populate_settings_from_assistance_file(rdpAssistanceFile* file, rdpSettings* settings);
FREERDP_API rdpAssistanceFile* freerdp_assistance_file_new();
FREERDP_API void freerdp_assistance_file_free(rdpAssistanceFile* file);
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_REMOTE_ASSISTANCE_H */

View File

@ -0,0 +1,186 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Multiparty Virtual Channel
*
* Copyright 2014 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.
*/
#ifndef FREERDP_CHANNEL_ENCOMSP_H
#define FREERDP_CHANNEL_ENCOMSP_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#define ENCOMSP_SVC_CHANNEL_NAME "encomsp"
struct _ENCOMSP_UNICODE_STRING
{
UINT16 cchString;
WCHAR wString[1024];
};
typedef struct _ENCOMSP_UNICODE_STRING ENCOMSP_UNICODE_STRING;
/* Filter Updated PDU Flags */
#define ENCOMSP_FILTER_ENABLED 0x0001
/* Application Created PDU Flags */
#define ENCOMSP_APPLICATION_SHARED 0x0001
/* Window Created PDU Flags */
#define ENCOMSP_WINDOW_SHARED 0x0001
/* Participant Created PDU Flags */
#define ENCOMSP_MAY_VIEW 0x0001
#define ENCOMSP_MAY_INTERACT 0x0002
#define ENCOMSP_IS_PARTICIPANT 0x0004
/* Participant Removed PDU Disconnection Types */
#define ENCOMSP_PARTICIPANT_DISCONNECTION_REASON_APP 0x00000000
#define ENCOMSP_PARTICIPANT_DISCONNECTION_REASON_CLI 0x00000002
/* Change Participant Control Level PDU Flags */
#define ENCOMSP_REQUEST_VIEW 0x0001
#define ENCOMSP_REQUEST_INTERACT 0x0002
#define ENCOMSP_ALLOW_CONTROL_REQUESTS 0x0008
/* PDU Order Types */
#define ODTYPE_FILTER_STATE_UPDATED 0x0001
#define ODTYPE_APP_REMOVED 0x0002
#define ODTYPE_APP_CREATED 0x0003
#define ODTYPE_WND_REMOVED 0x0004
#define ODTYPE_WND_CREATED 0x0005
#define ODTYPE_WND_SHOW 0x0006
#define ODTYPE_PARTICIPANT_REMOVED 0x0007
#define ODTYPE_PARTICIPANT_CREATED 0x0008
#define ODTYPE_PARTICIPANT_CTRL_CHANGED 0x0009
#define ODTYPE_GRAPHICS_STREAM_PAUSED 0x000A
#define ODTYPE_GRAPHICS_STREAM_RESUMED 0x000B
#define DEFINE_ENCOMSP_HEADER_COMMON() \
UINT16 Type; \
UINT16 Length
#define ENCOMSP_ORDER_HEADER_SIZE 4
struct _ENCOMSP_ORDER_HEADER
{
DEFINE_ENCOMSP_HEADER_COMMON();
};
typedef struct _ENCOMSP_ORDER_HEADER ENCOMSP_ORDER_HEADER;
struct _ENCOMSP_FILTER_UPDATED_PDU
{
DEFINE_ENCOMSP_HEADER_COMMON();
BYTE Flags;
};
typedef struct _ENCOMSP_FILTER_UPDATED_PDU ENCOMSP_FILTER_UPDATED_PDU;
struct _ENCOMSP_APPLICATION_CREATED_PDU
{
DEFINE_ENCOMSP_HEADER_COMMON();
UINT16 Flags;
UINT32 AppId;
ENCOMSP_UNICODE_STRING Name;
};
typedef struct _ENCOMSP_APPLICATION_CREATED_PDU ENCOMSP_APPLICATION_CREATED_PDU;
struct _ENCOMSP_APPLICATION_REMOVED_PDU
{
DEFINE_ENCOMSP_HEADER_COMMON();
UINT32 AppId;
};
typedef struct _ENCOMSP_APPLICATION_REMOVED_PDU ENCOMSP_APPLICATION_REMOVED_PDU;
struct _ENCOMSP_WINDOW_CREATED_PDU
{
DEFINE_ENCOMSP_HEADER_COMMON();
UINT16 Flags;
UINT32 AppId;
UINT32 WndId;
ENCOMSP_UNICODE_STRING Name;
};
typedef struct _ENCOMSP_WINDOW_CREATED_PDU ENCOMSP_WINDOW_CREATED_PDU;
struct _ENCOMSP_WINDOW_REMOVED_PDU
{
DEFINE_ENCOMSP_HEADER_COMMON();
UINT32 WndId;
};
typedef struct _ENCOMSP_WINDOW_REMOVED_PDU ENCOMSP_WINDOW_REMOVED_PDU;
struct _ENCOMSP_SHOW_WINDOW_PDU
{
DEFINE_ENCOMSP_HEADER_COMMON();
UINT32 WndId;
};
typedef struct _ENCOMSP_SHOW_WINDOW_PDU ENCOMSP_SHOW_WINDOW_PDU;
struct _ENCOMSP_PARTICIPANT_CREATED_PDU
{
DEFINE_ENCOMSP_HEADER_COMMON();
UINT32 ParticipantId;
UINT32 GroupId;
UINT16 Flags;
ENCOMSP_UNICODE_STRING FriendlyName;
};
typedef struct _ENCOMSP_PARTICIPANT_CREATED_PDU ENCOMSP_PARTICIPANT_CREATED_PDU;
struct _ENCOMSP_PARTICIPANT_REMOVED_PDU
{
DEFINE_ENCOMSP_HEADER_COMMON();
UINT32 ParticipantId;
UINT32 DiscType;
UINT32 DiscCode;
};
typedef struct _ENCOMSP_PARTICIPANT_REMOVED_PDU ENCOMSP_PARTICIPANT_REMOVED_PDU;
struct _ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU
{
DEFINE_ENCOMSP_HEADER_COMMON();
UINT16 Flags;
UINT32 ParticipantId;
};
typedef struct _ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU;
struct _ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU
{
DEFINE_ENCOMSP_HEADER_COMMON();
};
typedef struct _ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU;
struct _ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU
{
DEFINE_ENCOMSP_HEADER_COMMON();
};
typedef struct _ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU;
#endif /* FREERDP_CHANNEL_ENCOMSP_H */

View File

@ -0,0 +1,104 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Remote Assistance Virtual Channel
*
* Copyright 2014 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.
*/
#ifndef FREERDP_CHANNEL_REMDESK_H
#define FREERDP_CHANNEL_REMDESK_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#define REMDESK_SVC_CHANNEL_NAME "remdesk"
struct _REMDESK_CHANNEL_HEADER
{
UINT32 DataLength;
char ChannelName[32];
};
typedef struct _REMDESK_CHANNEL_HEADER REMDESK_CHANNEL_HEADER;
#define REMDESK_CHANNEL_CTL_NAME "RC_CTL"
#define REMDESK_CHANNEL_CTL_SIZE 22
struct _REMDESK_CTL_HEADER
{
UINT32 DataLength;
char ChannelName[32];
UINT32 msgType;
};
typedef struct _REMDESK_CTL_HEADER REMDESK_CTL_HEADER;
#define REMDESK_CTL_REMOTE_CONTROL_DESKTOP 1
#define REMDESK_CTL_RESULT 2
#define REMDESK_CTL_AUTHENTICATE 3
#define REMDESK_CTL_SERVER_ANNOUNCE 4
#define REMDESK_CTL_DISCONNECT 5
#define REMDESK_CTL_VERSIONINFO 6
#define REMDESK_CTL_ISCONNECTED 7
#define REMDESK_CTL_VERIFY_PASSWORD 8
#define REMDESK_CTL_EXPERT_ON_VISTA 9
#define REMDESK_CTL_RANOVICE_NAME 10
#define REMDESK_CTL_RAEXPERT_NAME 11
#define REMDESK_CTL_TOKEN 12
struct _REMDESK_CTL_VERSION_INFO_PDU
{
REMDESK_CTL_HEADER ctlHeader;
UINT32 versionMajor;
UINT32 versionMinor;
};
typedef struct _REMDESK_CTL_VERSION_INFO_PDU REMDESK_CTL_VERSION_INFO_PDU;
struct _REMDESK_CTL_AUTHENTICATE_PDU
{
REMDESK_CTL_HEADER ctlHeader;
char* raConnectionString;
char* expertBlob;
};
typedef struct _REMDESK_CTL_AUTHENTICATE_PDU REMDESK_CTL_AUTHENTICATE_PDU;
struct _REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU
{
REMDESK_CTL_HEADER ctlHeader;
char* raConnectionString;
};
typedef struct _REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU REMDESK_CTL_REMOTE_CONTROL_DESKTOP_PDU;
struct _REMDESK_CTL_VERIFY_PASSWORD_PDU
{
REMDESK_CTL_HEADER ctlHeader;
char* expertBlob;
};
typedef struct _REMDESK_CTL_VERIFY_PASSWORD_PDU REMDESK_CTL_VERIFY_PASSWORD_PDU;
struct _REMDESK_CTL_EXPERT_ON_VISTA_PDU
{
REMDESK_CTL_HEADER ctlHeader;
BYTE* EncryptedPassword;
UINT32 EncryptedPasswordLength;
};
typedef struct _REMDESK_CTL_EXPERT_ON_VISTA_PDU REMDESK_CTL_EXPERT_ON_VISTA_PDU;
#endif /* FREERDP_CHANNEL_REMDESK_H */

View File

@ -37,12 +37,8 @@
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/wtsapi.h>
#define WTSVirtualEventHandle 3 /* Extended */
#define WTSVirtualChannelReady 4 /* Extended */
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -86,10 +86,13 @@ FREERDP_API freerdp* freerdp_client_get_instance(rdpContext* context);
FREERDP_API HANDLE freerdp_client_get_thread(rdpContext* context);
FREERDP_API int freerdp_client_settings_parse_command_line(rdpSettings* settings, int argc, char** argv);
FREERDP_API int freerdp_client_settings_parse_connection_file(rdpSettings* settings, const char* filename);
FREERDP_API int freerdp_client_settings_parse_connection_file_buffer(rdpSettings* settings, const BYTE* buffer, size_t size);
FREERDP_API int freerdp_client_settings_write_connection_file(const rdpSettings* settings, const char* filename, BOOL unicode);
FREERDP_API int freerdp_client_settings_parse_assistance_file(rdpSettings* settings, const char* filename);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,61 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Multiparty Virtual Channel
*
* Copyright 2014 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.
*/
#ifndef FREERDP_CHANNEL_CLIENT_ENCOMSP_H
#define FREERDP_CHANNEL_CLIENT_ENCOMSP_H
#include <freerdp/channels/encomsp.h>
/**
* Client Interface
*/
typedef struct _encomsp_client_context EncomspClientContext;
typedef int (*pcEncomspFilterUpdated)(EncomspClientContext* context, ENCOMSP_FILTER_UPDATED_PDU* filterUpdated);
typedef int (*pcEncomspApplicationCreated)(EncomspClientContext* context, ENCOMSP_APPLICATION_CREATED_PDU* applicationCreated);
typedef int (*pcEncomspApplicationRemoved)(EncomspClientContext* context, ENCOMSP_APPLICATION_REMOVED_PDU* applicationRemoved);
typedef int (*pcEncomspWindowCreated)(EncomspClientContext* context, ENCOMSP_WINDOW_CREATED_PDU* windowCreated);
typedef int (*pcEncomspWindowRemoved)(EncomspClientContext* context, ENCOMSP_WINDOW_REMOVED_PDU* windowRemoved);
typedef int (*pcEncomspShowWindow)(EncomspClientContext* context, ENCOMSP_SHOW_WINDOW_PDU* showWindow);
typedef int (*pcEncomspParticipantCreated)(EncomspClientContext* context, ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated);
typedef int (*pcEncomspParticipantRemoved)(EncomspClientContext* context, ENCOMSP_PARTICIPANT_REMOVED_PDU* participantRemoved);
typedef int (*pcEncomspChangeParticipantControlLevel)(EncomspClientContext* context, ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* changeParticipantControlLevel);
typedef int (*pcEncomspGraphicsStreamPaused)(EncomspClientContext* context, ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU* graphicsStreamPaused);
typedef int (*pcEncomspGraphicsStreamResumed)(EncomspClientContext* context, ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU* graphicsStreamResumed);
struct _encomsp_client_context
{
void* handle;
void* custom;
pcEncomspFilterUpdated FilterUpdated;
pcEncomspApplicationCreated ApplicationCreated;
pcEncomspApplicationRemoved ApplicationRemoved;
pcEncomspWindowCreated WindowCreated;
pcEncomspWindowRemoved WindowRemoved;
pcEncomspShowWindow ShowWindow;
pcEncomspParticipantCreated ParticipantCreated;
pcEncomspParticipantRemoved ParticipantRemoved;
pcEncomspChangeParticipantControlLevel ChangeParticipantControlLevel;
pcEncomspGraphicsStreamPaused GraphicsStreamPaused;
pcEncomspGraphicsStreamResumed GraphicsStreamResumed;
};
#endif /* FREERDP_CHANNEL_CLIENT_ENCOMSP_H */

View File

@ -0,0 +1,38 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Remote Assistance Virtual Channel
*
* Copyright 2014 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.
*/
#ifndef FREERDP_CHANNEL_CLIENT_REMDESK_H
#define FREERDP_CHANNEL_CLIENT_REMDESK_H
#include <freerdp/channels/remdesk.h>
/**
* Client Interface
*/
typedef struct _remdesk_client_context RemdeskClientContext;
struct _remdesk_client_context
{
void* handle;
void* custom;
};
#endif /* FREERDP_CHANNEL_CLIENT_REMDESK_H */

View File

@ -0,0 +1,52 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Multiparty Virtual Channel
*
* Copyright 2014 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.
*/
#ifndef FREERDP_CHANNEL_SERVER_ENCOMSP_H
#define FREERDP_CHANNEL_SERVER_ENCOMSP_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/client/encomsp.h>
/**
* Server Interface
*/
typedef struct _encomsp_server_context EncomspServerContext;
typedef struct _encomsp_server_private EncomspServerPrivate;
typedef int (*psEncomspStart)(EncomspServerContext* context);
typedef int (*psEncomspStop)(EncomspServerContext* context);
struct _encomsp_server_context
{
HANDLE vcm;
psEncomspStart Start;
psEncomspStop Stop;
EncomspServerPrivate* priv;
};
FREERDP_API EncomspServerContext* encomsp_server_context_new(HANDLE vcm);
FREERDP_API void encomsp_server_context_free(EncomspServerContext* context);
#endif /* FREERDP_CHANNEL_SERVER_ENCOMSP_H */

View File

@ -30,13 +30,14 @@ typedef struct _rdpsnd_server_private RdpsndServerPrivate;
typedef int (*psRdpsndStart)(RdpsndServerContext* context);
typedef int (*psRdpsndStop)(RdpsndServerContext* context);
typedef BOOL (*psRdpsndServerInitialize)(RdpsndServerContext* context);
typedef BOOL (*psRdpsndServerInitialize)(RdpsndServerContext* context, BOOL ownThread);
typedef BOOL (*psRdpsndServerSelectFormat)(RdpsndServerContext* context, int client_format_index);
typedef BOOL (*psRdpsndServerSendSamples)(RdpsndServerContext* context, const void* buf, int nframes, UINT16 wTimestamp);
typedef BOOL (*psRdpsndServerConfirmBlock)(RdpsndServerContext* context, BYTE confirmBlockNum, UINT16 wtimestamp);
typedef BOOL (*psRdpsndServerSetVolume)(RdpsndServerContext* context, int left, int right);
typedef BOOL (*psRdpsndServerClose)(RdpsndServerContext* context);
typedef void (*psRdpsndServerActivated)(RdpsndServerContext* context);
struct _rdpsnd_server_context
@ -111,7 +112,12 @@ extern "C" {
#endif
FREERDP_API RdpsndServerContext* rdpsnd_server_context_new(HANDLE vcm);
FREERDP_API void rdpsnd_server_context_reset(RdpsndServerContext *);
FREERDP_API void rdpsnd_server_context_free(RdpsndServerContext* context);
FREERDP_API HANDLE rdpsnd_server_get_event_handle(RdpsndServerContext *context);
FREERDP_API BOOL rdpsnd_server_handle_messages(RdpsndServerContext *context);
FREERDP_API BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s);
#ifdef __cplusplus
}

View File

@ -0,0 +1,53 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Remote Assistance Virtual Channel
*
* Copyright 2014 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.
*/
#ifndef FREERDP_CHANNEL_SERVER_REMDESK_H
#define FREERDP_CHANNEL_SERVER_REMDESK_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/client/remdesk.h>
/**
* Server Interface
*/
typedef struct _remdesk_server_context RemdeskServerContext;
typedef struct _remdesk_server_private RemdeskServerPrivate;
typedef int (*psRemdeskStart)(RemdeskServerContext* context);
typedef int (*psRemdeskStop)(RemdeskServerContext* context);
struct _remdesk_server_context
{
HANDLE vcm;
psRemdeskStart Start;
psRemdeskStop Stop;
RemdeskServerPrivate* priv;
};
FREERDP_API RemdeskServerContext* remdesk_server_context_new(HANDLE vcm);
FREERDP_API void remdesk_server_context_free(RemdeskServerContext* context);
#endif /* FREERDP_CHANNEL_SERVER_REMDESK_H */

View File

@ -586,6 +586,11 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_DisableCursorShadow 966
#define FreeRDP_DisableCursorBlinking 967
#define FreeRDP_AllowDesktopComposition 968
#define FreeRDP_RemoteAssistanceMode 1024
#define FreeRDP_RemoteAssistanceSessionId 1025
#define FreeRDP_RemoteAssistancePassStub 1026
#define FreeRDP_RemoteAssistancePassword 1027
#define FreeRDP_RemoteAssistanceRCTicket 1028
#define FreeRDP_TlsSecurity 1088
#define FreeRDP_NlaSecurity 1089
#define FreeRDP_RdpSecurity 1090
@ -655,6 +660,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_CredentialsFromStdin 1604
#define FreeRDP_ComputerName 1664
#define FreeRDP_ConnectionFile 1728
#define FreeRDP_AssistanceFile 1729
#define FreeRDP_HomePath 1792
#define FreeRDP_ConfigPath 1793
#define FreeRDP_CurrentPath 1794
@ -936,7 +942,14 @@ struct rdp_settings
ALIGN64 BOOL DisableCursorBlinking; /* 967 */
ALIGN64 BOOL AllowDesktopComposition; /* 968 */
UINT64 padding1024[1024 - 969]; /* 969 */
UINT64 padding1088[1088 - 1024]; /* 1024 */
/* Remote Assistance */
ALIGN64 BOOL RemoteAssistanceMode; /* 1024 */
ALIGN64 char* RemoteAssistanceSessionId; /* 1025 */
ALIGN64 char* RemoteAssistancePassStub; /* 1026 */
ALIGN64 char* RemoteAssistancePassword; /* 1027 */
ALIGN64 char* RemoteAssistanceRCTicket; /* 1028 */
UINT64 padding1088[1088 - 1029]; /* 1029 */
/**
* X.224 Connection Request/Confirm
@ -1048,7 +1061,8 @@ struct rdp_settings
/* Files */
ALIGN64 char* ConnectionFile; /* 1728 */
UINT64 padding1792[1792 - 1729]; /* 1729 */
ALIGN64 char* AssistanceFile; /* 1729 */
UINT64 padding1792[1792 - 1730]; /* 1730 */
/* Paths */
ALIGN64 char* HomePath; /* 1792 */

View File

@ -20,15 +20,22 @@ set(MODULE_PREFIX "FREERDP_COMMON")
set(${MODULE_PREFIX}_SRCS
addin.c
settings.c)
settings.c
assistance.c)
add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
MONOLITHIC ${MONOLITHIC_BUILD}
SOURCES ${${MODULE_PREFIX}_SRCS}
EXPORT)
include_directories(${OPENSSL_INCLUDE_DIR})
include_directories(${ZLIB_INCLUDE_DIRS})
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib")
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES})
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-crt winpr-path winpr-file winpr-library winpr-utils)
@ -42,3 +49,6 @@ endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
if(BUILD_TESTING)
add_subdirectory(test)
endif()

View File

@ -0,0 +1,989 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Remote Assistance
*
* Copyright 2014 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/windows.h>
#include <openssl/ssl.h>
#include <openssl/md5.h>
#include <openssl/rc4.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/engine.h>
#include <freerdp/client/file.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/assistance.h>
/**
* Password encryption in establishing a remote assistance session of type 1:
* http://blogs.msdn.com/b/openspecification/archive/2011/10/31/password-encryption-in-establishing-a-remote-assistance-session-of-type-1.aspx
*
* Creation of PassStub for the Remote Assistance Ticket:
* http://social.msdn.microsoft.com/Forums/en-US/6316c3f4-ea09-4343-a4a1-9cca46d70d28/creation-of-passstub-for-the-remote-assistance-ticket?forum=os_windowsprotocols
*/
/**
* CryptDeriveKey Function:
* http://msdn.microsoft.com/en-us/library/windows/desktop/aa379916/
*
* Let n be the required derived key length, in bytes.
* The derived key is the first n bytes of the hash value after the hash computation
* has been completed by CryptDeriveKey. If the hash is not a member of the SHA-2
* family and the required key is for either 3DES or AES, the key is derived as follows:
*
* Form a 64-byte buffer by repeating the constant 0x36 64 times.
* Let k be the length of the hash value that is represented by the input parameter hBaseData.
* Set the first k bytes of the buffer to the result of an XOR operation of the first k bytes
* of the buffer with the hash value that is represented by the input parameter hBaseData.
*
* Form a 64-byte buffer by repeating the constant 0x5C 64 times.
* Set the first k bytes of the buffer to the result of an XOR operation of the first k bytes
* of the buffer with the hash value that is represented by the input parameter hBaseData.
*
* Hash the result of step 1 by using the same hash algorithm as that used to compute the hash
* value that is represented by the hBaseData parameter.
*
* Hash the result of step 2 by using the same hash algorithm as that used to compute the hash
* value that is represented by the hBaseData parameter.
*
* Concatenate the result of step 3 with the result of step 4.
* Use the first n bytes of the result of step 5 as the derived key.
*/
int freerdp_assistance_crypt_derive_key_sha1(BYTE* hash, int hashLength, BYTE* key, int keyLength)
{
int i;
BYTE* buffer;
BYTE pad1[64];
BYTE pad2[64];
SHA_CTX hashCtx;
memset(pad1, 0x36, 64);
memset(pad2, 0x5C, 64);
for (i = 0; i < hashLength; i++)
{
pad1[i] ^= hash[i];
pad2[i] ^= hash[i];
}
buffer = (BYTE*) calloc(1, hashLength * 2);
if (!buffer)
return -1;
SHA1_Init(&hashCtx);
SHA1_Update(&hashCtx, pad1, 64);
SHA1_Final((void*) buffer, &hashCtx);
SHA1_Init(&hashCtx);
SHA1_Update(&hashCtx, pad2, 64);
SHA1_Final((void*) &buffer[hashLength], &hashCtx);
CopyMemory(key, buffer, keyLength);
free(buffer);
return 1;
}
int freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list)
{
int i;
char* p;
char* q;
char* str;
int count;
int length;
char** tokens;
count = 1;
str = _strdup(list);
if (!str)
return -1;
length = strlen(str);
for (i = 0; i < length; i++)
{
if (str[i] == ';')
count++;
}
tokens = (char**) malloc(sizeof(char*) * count);
count = 0;
tokens[count++] = str;
for (i = 0; i < length; i++)
{
if (str[i] == ';')
{
str[i] = '\0';
tokens[count++] = &str[i + 1];
}
}
for (i = 0; i < count; i++)
{
length = strlen(tokens[i]);
if (length > 8)
{
if (strncmp(tokens[i], "169.254.", 8) == 0)
continue;
}
p = tokens[i];
q = strchr(p, ':');
if (!q)
return -1;
q[0] = '\0';
q++;
file->MachineAddress = _strdup(p);
file->MachinePort = (UINT32) atoi(q);
break;
}
return 1;
}
int freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file)
{
int i;
char* str;
int count;
int length;
char* tokens[8];
/**
* <ProtocolVersion>,<protocolType>,<machineAddressList>,<assistantAccountPwd>,
* <RASessionID>,<RASessionName>,<RASessionPwd>,<protocolSpecificParms>
*/
count = 1;
str = _strdup(file->RCTicket);
if (!str)
return -1;
length = strlen(str);
for (i = 0; i < length; i++)
{
if (str[i] == ',')
count++;
}
if (count != 8)
return -1;
count = 0;
tokens[count++] = str;
for (i = 0; i < length; i++)
{
if (str[i] == ',')
{
str[i] = '\0';
tokens[count++] = &str[i + 1];
}
}
if (strcmp(tokens[0], "65538") != 0)
return -1;
if (strcmp(tokens[1], "1") != 0)
return -1;
if (strcmp(tokens[3], "*") != 0)
return -1;
if (strcmp(tokens[5], "*") != 0)
return -1;
if (strcmp(tokens[6], "*") != 0)
return -1;
file->RASessionId = _strdup(tokens[4]);
if (!file->RASessionId)
return -1;
file->RASpecificParams = _strdup(tokens[7]);
if (!file->RASpecificParams)
return -1;
freerdp_assistance_parse_address_list(file, tokens[2]);
free(str);
return 1;
}
/**
* Decrypted Connection String 2:
*
* <E>
* <A KH="BNRjdu97DyczQSRuMRrDWoue+HA=" ID="+ULZ6ifjoCa6cGPMLQiGHRPwkg6VyJqGwxMnO6GcelwUh9a6/FBq3It5ADSndmLL"/>
* <C>
* <T ID="1" SID="0">
* <L P="49228" N="fe80::1032:53d9:5a01:909b%3"/>
* <L P="49229" N="fe80::3d8f:9b2d:6b4e:6aa%6"/>
* <L P="49230" N="192.168.1.200"/>
* <L P="49231" N="169.254.6.170"/>
* </T>
* </C>
* </E>
*/
int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file)
{
char* p;
char* q;
char* str;
size_t length;
str = _strdup(file->ConnectionString2);
if (!str)
return -1;
p = strstr(str, "<E>");
if (!p)
return -1;
p = strstr(str, "<C>");
if (!p)
return -1;
/* Auth String Node (<A>) */
p = strstr(str, "<A");
if (!p)
return -1;
p = strstr(p, "KH=\"");
if (p)
{
p += sizeof("KH=\"") - 1;
q = strchr(p, '"');
if (!q)
return -1;
length = q - p;
free(file->RASpecificParams);
file->RASpecificParams = (char*) malloc(length + 1);
if (!file->RASpecificParams)
return -1;
CopyMemory(file->RASpecificParams, p, length);
file->RASpecificParams[length] = '\0';
p += length;
}
p = strstr(p, "ID=\"");
if (p)
{
p += sizeof("ID=\"") - 1;
q = strchr(p, '"');
if (!q)
return -1;
length = q - p;
free(file->RASessionId);
file->RASessionId = (char*) malloc(length + 1);
if (!file->RASessionId)
return -1;
CopyMemory(file->RASessionId, p, length);
file->RASessionId[length] = '\0';
p += length;
}
free(str);
return 1;
}
char* freerdp_assistance_construct_expert_blob(const char* name, const char* pass)
{
int size;
int nameLength;
int passLength;
char* ExpertBlob = NULL;
if (!name || !pass)
return NULL;
nameLength = strlen(name) + strlen("NAME=");
passLength = strlen(pass) + strlen("PASS=");
size = nameLength + passLength + 64;
ExpertBlob = (char*) calloc(1, size);
if (!ExpertBlob)
return NULL;
sprintf_s(ExpertBlob, size, "%d;NAME=%s%d;PASS=%s",
nameLength, name, passLength, pass);
return ExpertBlob;
}
BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub, int* pEncryptedSize)
{
int status;
MD5_CTX md5Ctx;
int cbPasswordW;
int cbPassStubW;
int EncryptedSize;
BYTE PasswordHash[16];
EVP_CIPHER_CTX rc4Ctx;
BYTE *pbIn, *pbOut;
int cbOut, cbIn, cbFinal;
WCHAR* PasswordW = NULL;
WCHAR* PassStubW = NULL;
status = ConvertToUnicode(CP_UTF8, 0, password, -1, &PasswordW, 0);
if (status <= 0)
return NULL;
cbPasswordW = (status - 1) * 2;
MD5_Init(&md5Ctx);
MD5_Update(&md5Ctx, PasswordW, cbPasswordW);
MD5_Final((void*) PasswordHash, &md5Ctx);
status = ConvertToUnicode(CP_UTF8, 0, passStub, -1, &PassStubW, 0);
if (status <= 0)
return NULL;
cbPassStubW = (status - 1) * 2;
EncryptedSize = cbPassStubW + 4;
pbIn = (BYTE*) calloc(1, EncryptedSize);
pbOut = (BYTE*) calloc(1, EncryptedSize);
if (!pbIn)
return NULL;
if (!EncryptedSize)
return NULL;
*((UINT32*) pbIn) = cbPassStubW;
CopyMemory(&pbIn[4], PassStubW, cbPassStubW);
EVP_CIPHER_CTX_init(&rc4Ctx);
status = EVP_EncryptInit_ex(&rc4Ctx, EVP_rc4(), NULL, NULL, NULL);
if (!status)
{
fprintf(stderr, "EVP_CipherInit_ex failure\n");
return NULL;
}
status = EVP_EncryptInit_ex(&rc4Ctx, NULL, NULL, PasswordHash, NULL);
if (!status)
{
fprintf(stderr, "EVP_CipherInit_ex failure\n");
return NULL;
}
cbOut = cbFinal = 0;
cbIn = EncryptedSize;
status = EVP_EncryptUpdate(&rc4Ctx, pbOut, &cbOut, pbIn, cbIn);
if (!status)
{
fprintf(stderr, "EVP_CipherUpdate failure\n");
return NULL;
}
status = EVP_EncryptFinal_ex(&rc4Ctx, pbOut + cbOut, &cbFinal);
if (!status)
{
fprintf(stderr, "EVP_CipherFinal_ex failure\n");
return NULL;
}
EVP_CIPHER_CTX_cleanup(&rc4Ctx);
free(pbIn);
free(PasswordW);
free(PassStubW);
*pEncryptedSize = EncryptedSize;
return pbOut;
}
int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password)
{
int status;
SHA_CTX shaCtx;
int cbPasswordW;
int cchOutW = 0;
WCHAR* pbOutW = NULL;
EVP_CIPHER_CTX aesDec;
WCHAR* PasswordW = NULL;
BYTE *pbIn, *pbOut;
int cbOut, cbIn, cbFinal;
BYTE DerivedKey[AES_BLOCK_SIZE];
BYTE InitializationVector[AES_BLOCK_SIZE];
BYTE PasswordHash[SHA_DIGEST_LENGTH];
status = ConvertToUnicode(CP_UTF8, 0, password, -1, &PasswordW, 0);
if (status <= 0)
return -1;
cbPasswordW = (status - 1) * 2;
SHA1_Init(&shaCtx);
SHA1_Update(&shaCtx, PasswordW, cbPasswordW);
SHA1_Final((void*) PasswordHash, &shaCtx);
status = freerdp_assistance_crypt_derive_key_sha1(PasswordHash, sizeof(PasswordHash),
DerivedKey, sizeof(DerivedKey));
if (status < 0)
return -1;
ZeroMemory(InitializationVector, sizeof(InitializationVector));
EVP_CIPHER_CTX_init(&aesDec);
status = EVP_DecryptInit_ex(&aesDec, EVP_aes_128_cbc(), NULL, NULL, NULL);
if (status != 1)
return -1;
EVP_CIPHER_CTX_set_key_length(&aesDec, (128 / 8));
EVP_CIPHER_CTX_set_padding(&aesDec, 0);
status = EVP_DecryptInit_ex(&aesDec, EVP_aes_128_cbc(), NULL, DerivedKey, InitializationVector);
if (status != 1)
return -1;
cbOut = cbFinal = 0;
cbIn = file->EncryptedLHTicketLength;
pbIn = (BYTE*) file->EncryptedLHTicket;
pbOut = (BYTE*) calloc(1, cbIn + AES_BLOCK_SIZE + 2);
if (!pbOut)
return -1;
status = EVP_DecryptUpdate(&aesDec, pbOut, &cbOut, pbIn, cbIn);
if (status != 1)
return -1;
status = EVP_DecryptFinal_ex(&aesDec, pbOut + cbOut, &cbFinal);
if (status != 1)
{
fprintf(stderr, "EVP_DecryptFinal_ex failure\n");
return -1;
}
EVP_CIPHER_CTX_cleanup(&aesDec);
cbOut += cbFinal;
cbFinal = 0;
pbOutW = (WCHAR*) pbOut;
cchOutW = cbOut / 2;
file->ConnectionString2 = NULL;
status = ConvertFromUnicode(CP_UTF8, 0, pbOutW, cchOutW, &file->ConnectionString2, 0, NULL, NULL);
if (status <= 0)
return -1;
free(PasswordW);
free(pbOut);
status = freerdp_assistance_parse_connection_string2(file);
printf("freerdp_assistance_parse_connection_string2: %d\n", status);
return 1;
}
int freerdp_assistance_decrypt(rdpAssistanceFile* file, const char* password)
{
int status = 1;
file->EncryptedPassStub = freerdp_assistance_encrypt_pass_stub(password,
file->PassStub, &file->EncryptedPassStubLength);
if (!file->EncryptedPassStub)
return -1;
if (file->Type > 1)
{
status = freerdp_assistance_decrypt2(file, password);
}
return status;
}
BYTE* freerdp_assistance_hex_string_to_bin(const char* str, int* size)
{
char c;
int length;
BYTE* buffer;
int i, ln, hn;
length = strlen(str);
if ((length % 2) != 0)
return NULL;
length /= 2;
*size = length;
buffer = (BYTE*) malloc(length);
if (!buffer)
return NULL;
for (i = 0; i < length; i++)
{
hn = ln = 0;
c = str[(i * 2) + 0];
if ((c >= '0') && (c <= '9'))
hn = c - '0';
else if ((c >= 'a') && (c <= 'f'))
hn = (c - 'a') + 10;
else if ((c >= 'A') && (c <= 'F'))
hn = (c - 'A') + 10;
c = str[(i * 2) + 1];
if ((c >= '0') && (c <= '9'))
ln = c - '0';
else if ((c >= 'a') && (c <= 'f'))
ln = (c - 'a') + 10;
else if ((c >= 'A') && (c <= 'F'))
ln = (c - 'A') + 10;
buffer[i] = (hn << 4) | ln;
}
return buffer;
}
char* freerdp_assistance_bin_to_hex_string(const BYTE* data, int size)
{
int i;
char* p;
int ln, hn;
char bin2hex[] = "0123456789ABCDEF";
p = (char*) malloc((size + 1) * 2);
for (i = 0; i < size; i++)
{
ln = data[i] & 0xF;
hn = (data[i] >> 4) & 0xF;
p[i * 2] = bin2hex[hn];
p[(i * 2) + 1] = bin2hex[ln];
}
p[size * 2] = '\0';
return p;
}
int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* buffer, size_t size)
{
char* p;
char* q;
char* r;
int value;
int status;
size_t length;
p = strstr(buffer, "UPLOADINFO");
if (!p)
return -1;
p = strstr(p + sizeof("UPLOADINFO") - 1, "TYPE=\"");
if (!p)
return -1;
p = strstr(buffer, "UPLOADDATA");
if (!p)
return -1;
/* Parse USERNAME */
p = strstr(buffer, "USERNAME=\"");
if (p)
{
p += sizeof("USERNAME=\"") - 1;
q = strchr(p, '"');
if (!q)
return -1;
length = q - p;
file->Username = (char*) malloc(length + 1);
if (!file->Username)
return -1;
CopyMemory(file->Username, p, length);
file->Username[length] = '\0';
}
/* Parse LHTICKET */
p = strstr(buffer, "LHTICKET=\"");
if (p)
{
p += sizeof("LHTICKET=\"") - 1;
q = strchr(p, '"');
if (!q)
return -1;
length = q - p;
file->LHTicket = (char*) malloc(length + 1);
if (!file->LHTicket)
return -1;
CopyMemory(file->LHTicket, p, length);
file->LHTicket[length] = '\0';
}
/* Parse RCTICKET */
p = strstr(buffer, "RCTICKET=\"");
if (p)
{
p += sizeof("RCTICKET=\"") - 1;
q = strchr(p, '"');
if (!q)
return -1;
length = q - p;
file->RCTicket = (char*) malloc(length + 1);
if (!file->RCTicket)
return -1;
CopyMemory(file->RCTicket, p, length);
file->RCTicket[length] = '\0';
}
/* Parse RCTICKETENCRYPTED */
p = strstr(buffer, "RCTICKETENCRYPTED=\"");
if (p)
{
p += sizeof("RCTICKETENCRYPTED=\"") - 1;
q = strchr(p, '"');
if (!q)
return -1;
length = q - p;
if ((length == 1) && (p[0] == '1'))
file->RCTicketEncrypted = TRUE;
}
/* Parse PassStub */
p = strstr(buffer, "PassStub=\"");
if (p)
{
p += sizeof("PassStub=\"") - 1;
q = strchr(p, '"');
if (!q)
return -1;
length = q - p;
file->PassStub = (char*) malloc(length + 1);
if (!file->PassStub)
return -1;
CopyMemory(file->PassStub, p, length);
file->PassStub[length] = '\0';
}
/* Parse DtStart */
p = strstr(buffer, "DtStart=\"");
if (p)
{
p += sizeof("DtStart=\"") - 1;
q = strchr(p, '"');
if (!q)
return -1;
length = q - p;
r = (char*) malloc(length + 1);
if (!r)
return -1;
CopyMemory(r, p, length);
r[length] = '\0';
value = atoi(r);
free(r);
if (value < 0)
return -1;
file->DtStart = (UINT32) value;
}
/* Parse DtLength */
p = strstr(buffer, "DtLength=\"");
if (p)
{
p += sizeof("DtLength=\"") - 1;
q = strchr(p, '"');
if (!q)
return -1;
length = q - p;
r = (char*) malloc(length + 1);
if (!r)
return -1;
CopyMemory(r, p, length);
r[length] = '\0';
value = atoi(r);
free(r);
if (value < 0)
return -1;
file->DtLength = (UINT32) value;
}
/* Parse L (LowSpeed) */
p = strstr(buffer, " L=\"");
if (p)
{
p += sizeof(" L=\"") - 1;
q = strchr(p, '"');
if (!q)
return -1;
length = q - p;
if ((length == 1) && (p[0] == '1'))
file->LowSpeed = TRUE;
}
file->Type = (file->LHTicket) ? 2 : 1;
if (file->LHTicket)
{
file->EncryptedLHTicket = freerdp_assistance_hex_string_to_bin(file->LHTicket,
&file->EncryptedLHTicketLength);
}
status = freerdp_assistance_parse_connection_string1(file);
if (status < 0)
{
fprintf(stderr, "freerdp_assistance_parse_connection_string1 failure: %d\n", status);
return -1;
}
return 1;
}
int freerdp_assistance_parse_file(rdpAssistanceFile* file, const char* name)
{
int status;
BYTE* buffer;
FILE* fp = NULL;
size_t readSize;
long int fileSize;
fp = fopen(name, "r");
if (!fp)
return -1;
fseek(fp, 0, SEEK_END);
fileSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
if (fileSize < 1)
{
fclose(fp);
return -1;
}
buffer = (BYTE*) malloc(fileSize + 2);
readSize = fread(buffer, fileSize, 1, fp);
if (!readSize)
{
if (!ferror(fp))
readSize = fileSize;
}
fclose(fp);
if (readSize < 1)
{
free(buffer);
buffer = NULL;
return -1;
}
buffer[fileSize] = '\0';
buffer[fileSize + 1] = '\0';
status = freerdp_assistance_parse_file_buffer(file, (char*) buffer, fileSize);
free(buffer);
return status;
}
int freerdp_client_populate_settings_from_assistance_file(rdpAssistanceFile* file, rdpSettings* settings)
{
freerdp_set_param_bool(settings, FreeRDP_RemoteAssistanceMode, TRUE);
if (!file->RASessionId)
return -1;
freerdp_set_param_string(settings, FreeRDP_RemoteAssistanceSessionId, file->RASessionId);
if (file->RCTicket)
freerdp_set_param_string(settings, FreeRDP_RemoteAssistanceRCTicket, file->RCTicket);
if (file->PassStub)
freerdp_set_param_string(settings, FreeRDP_RemoteAssistancePassStub, file->PassStub);
if (!file->MachineAddress)
return -1;
freerdp_set_param_string(settings, FreeRDP_ServerHostname, file->MachineAddress);
freerdp_set_param_uint32(settings, FreeRDP_ServerPort, file->MachinePort);
return 1;
}
rdpAssistanceFile* freerdp_assistance_file_new()
{
rdpAssistanceFile* file;
file = (rdpAssistanceFile*) calloc(1, sizeof(rdpAssistanceFile));
if (file)
{
}
return file;
}
void freerdp_assistance_file_free(rdpAssistanceFile* file)
{
if (!file)
return;
free(file->Username);
free(file->LHTicket);
free(file->RCTicket);
free(file->PassStub);
free(file->ConnectionString1);
free(file->ConnectionString2);
free(file->EncryptedLHTicket);
free(file->RASessionId);
free(file->RASpecificParams);
free(file->MachineAddress);
free(file->EncryptedPassStub);
free(file);
}

View File

@ -819,6 +819,10 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id)
return settings->AllowDesktopComposition;
break;
case FreeRDP_RemoteAssistanceMode:
return settings->RemoteAssistanceMode;
break;
case FreeRDP_TlsSecurity:
return settings->TlsSecurity;
break;
@ -1304,6 +1308,10 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
settings->AllowDesktopComposition = param;
break;
case FreeRDP_RemoteAssistanceMode:
settings->RemoteAssistanceMode = param;
break;
case FreeRDP_TlsSecurity:
settings->TlsSecurity = param;
break;
@ -2378,6 +2386,22 @@ char* freerdp_get_param_string(rdpSettings* settings, int id)
return settings->DynamicDSTTimeZoneKeyName;
break;
case FreeRDP_RemoteAssistanceSessionId:
return settings->RemoteAssistanceSessionId;
break;
case FreeRDP_RemoteAssistancePassStub:
return settings->RemoteAssistancePassStub;
break;
case FreeRDP_RemoteAssistancePassword:
return settings->RemoteAssistancePassword;
break;
case FreeRDP_RemoteAssistanceRCTicket:
return settings->RemoteAssistanceRCTicket;
break;
case FreeRDP_AuthenticationServiceClass:
return settings->AuthenticationServiceClass;
break;
@ -2422,6 +2446,10 @@ char* freerdp_get_param_string(rdpSettings* settings, int id)
return settings->ConnectionFile;
break;
case FreeRDP_AssistanceFile:
return settings->AssistanceFile;
break;
case FreeRDP_HomePath:
return settings->HomePath;
break;
@ -2563,6 +2591,26 @@ int freerdp_set_param_string(rdpSettings* settings, int id, const char* param)
settings->DynamicDSTTimeZoneKeyName = _strdup(param);
break;
case FreeRDP_RemoteAssistanceSessionId:
free(settings->RemoteAssistanceSessionId);
settings->RemoteAssistanceSessionId = _strdup(param);
break;
case FreeRDP_RemoteAssistancePassStub:
free(settings->RemoteAssistancePassStub);
settings->RemoteAssistancePassStub = _strdup(param);
break;
case FreeRDP_RemoteAssistancePassword:
free(settings->RemoteAssistancePassword);
settings->RemoteAssistancePassword = _strdup(param);
break;
case FreeRDP_RemoteAssistanceRCTicket:
free(settings->RemoteAssistanceRCTicket);
settings->RemoteAssistanceRCTicket = _strdup(param);
break;
case FreeRDP_AuthenticationServiceClass:
free(settings->AuthenticationServiceClass);
settings->AuthenticationServiceClass = _strdup(param);
@ -2618,6 +2666,11 @@ int freerdp_set_param_string(rdpSettings* settings, int id, const char* param)
settings->ConnectionFile = _strdup(param);
break;
case FreeRDP_AssistanceFile:
free(settings->AssistanceFile);
settings->AssistanceFile = _strdup(param);
break;
case FreeRDP_HomePath:
free(settings->HomePath);
settings->HomePath = _strdup(param);

3
libfreerdp/common/test/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
TestCommon
TestCommon.c

View File

@ -0,0 +1,31 @@
set(MODULE_NAME "TestCommon")
set(MODULE_PREFIX "TEST_COMMON")
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS
TestCommonAssistance.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}
${${MODULE_PREFIX}_TESTS})
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-common)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
foreach(test ${${MODULE_PREFIX}_TESTS})
get_filename_component(TestName ${test} NAME_WE)
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Common/Test")

View File

@ -0,0 +1,183 @@
#include <winpr/crt.h>
#include <winpr/print.h>
#include <freerdp/assistance.h>
const char* TEST_MSRC_INCIDENT_PASSWORD_TYPE1 = "Password1";
static const char* TEST_MSRC_INCIDENT_FILE_TYPE1 =
"<?xml version=\"1.0\" encoding=\"Unicode\" ?>"
"<UPLOADINFO TYPE=\"Escalated\">"
"<UPLOADDATA "
"USERNAME=\"Administrator\" "
"RCTICKET=\"65538,1,10.0.3.105:3389;winxpsp3.contoso3.com:3389,*,"
"rb+v0oPmEISmi8N2zK/vuhgul/ABqlDt6wW0VxMyxK8=,*,*,IuaRySSbPDNna4+2mKcsKxsbJFI=\""
"RCTICKETENCRYPTED=\"1\" "
"DtStart=\"1314905741\" "
"DtLength=\"180\" "
"PassStub=\"RT=0PvIndan52*\" "
"L=\"0\" />"
"</UPLOADINFO>";
const BYTE TEST_MSRC_INCIDENT_EXPERT_BLOB_TYPE1[32] =
"\x3C\x9C\xAE\x0B\xCE\x7A\xB1\x5C\x8A\xAC\x01\xD6\x76\x04\x5E\xDF"
"\x3F\xFA\xF0\x92\xE2\xDE\x36\x8A\x20\x17\xE6\x8A\x0D\xED\x7C\x90";
const char* TEST_MSRC_INCIDENT_PASSWORD_TYPE2 = "48BJQ853X3B4";
static const char* TEST_MSRC_INCIDENT_FILE_TYPE2 =
"<?xml version=\"1.0\"?>"
"<UPLOADINFO TYPE=\"Escalated\">"
"<UPLOADDATA USERNAME=\"awake\" "
"LHTICKET=\""
"20FCC407AA53E95F8505AB56D485D26835064B03AF86CDA326248FD304626AD4"
"DBDBDFFE0C473228EFFF7A1E6CEB445BBEC429294BB6616BBB600854438DDFB5"
"82FC377CF65A2060EB3221647643C9B29BF5EC320856180B34D1BE9827A528C7"
"E8F0DCD53C8D38F974160FEE317458FAC9DBDBA7B972D21DF3BC5B1AF0E01878"
"65F07A3B915618C03E6EAF843FC1185770A1208C29C836DBCA5A040CB276D3C4"
"1DDE2FA8CA9627E5E74FA750A92C0E01AD6C3D1000A5B1479DEB899BF5BCD402"
"CE3BB3BF104CE0286C3F985AA711943C88C5EEEEE86F35B63F68883A90ADBCFD"
"CBBAE3EAB993EFD9148E1A21D092CE9498695943946236D65D20B4A38D724C61"
"72319E38E19C04E98EBC03F56A4A190E971F8EAEBFE6B415A3A2D8F35F7BF785"
"26B9BFAAB48D11BDD6C905EFE503D2265678E1EAD2F2F124E570667F04103180"
"2F63587276C14E6A5AB436CE234F722CE7C9B5D244508F14C012E84A49FE6992"
"3F30320ABB3641F1EFA66205F3EA709E7E1C3E6874BB9642486FB96D2730CDF4"
"514AA738167F00FC13B2978AED1D6678413FDF62008B03DD729E36173BE02742"
"B69CAD44938512D0F56335394759338AF6ADBCF39CE829116D97435085D05BB5"
"9320A134698050DCDBE01305A6B4712FD6BD48958BD2DC497498FF35CAECC9A8"
"2C97FD1A5B5EC4BAF5FFB75A1471B765C465B35A7C950019066BB219B391C6E9"
"8AE8FD2038E774F36F226D9FB9A38BCC313785612165D1EF69D19E2B9CF6E0F7"
"FE1ECCF00AB81F9E8B626363CA82FAC719A3B7D243325C9D6042B2488EC95B80"
"A31273FF9B72FBBB86F946E6D3DF8816BE4533F0B547C8BC028309EA9784C1E6\" "
"RCTICKET=\"65538,1,192.168.1.200:49230;169.254.6.170:49231,*,"
"+ULZ6ifjoCa6cGPMLQiGHRPwkg6VyJqGwxMnO6GcelwUh9a6/FBq3It5ADSndmLL,"
"*,*,BNRjdu97DyczQSRuMRrDWoue+HA=\" "
"PassStub=\"WB^6HsrIaFmEpi\" "
"RCTICKETENCRYPTED=\"1\" "
"DtStart=\"1403972263\" "
"DtLength=\"14400\" "
"L=\"0\"/>"
"</UPLOADINFO>";
/**
* Decrypted Connection String 2:
*
* <E>
* <A KH="BNRjdu97DyczQSRuMRrDWoue+HA=" ID="+ULZ6ifjoCa6cGPMLQiGHRPwkg6VyJqGwxMnO6GcelwUh9a6/FBq3It5ADSndmLL"/>
* <C>
* <T ID="1" SID="0">
* <L P="49228" N="fe80::1032:53d9:5a01:909b%3"/>
* <L P="49229" N="fe80::3d8f:9b2d:6b4e:6aa%6"/>
* <L P="49230" N="192.168.1.200"/>
* <L P="49231" N="169.254.6.170"/>
* </T>
* </C>
* </E>
*/
int test_msrsc_incident_file_type1()
{
int status;
char* pass;
char* expertBlob;
rdpAssistanceFile* file;
file = freerdp_assistance_file_new();
status = freerdp_assistance_parse_file_buffer(file,
TEST_MSRC_INCIDENT_FILE_TYPE1, sizeof(TEST_MSRC_INCIDENT_FILE_TYPE1));
printf("freerdp_assistance_parse_file_buffer: %d\n", status);
if (status < 0)
return -1;
printf("Username: %s\n", file->Username);
printf("LHTicket: %s\n", file->LHTicket);
printf("RCTicket: %s\n", file->RCTicket);
printf("RCTicketEncrypted: %d\n", file->RCTicketEncrypted);
printf("PassStub: %s\n", file->PassStub);
printf("DtStart: %d\n", file->DtStart);
printf("DtLength: %d\n", file->DtLength);
printf("LowSpeed: %d\n", file->LowSpeed);
printf("RASessionId: %s\n", file->RASessionId);
printf("RASpecificParams: %s\n", file->RASpecificParams);
printf("MachineAddress: %s\n", file->MachineAddress);
printf("MachinePort: %d\n", (int) file->MachinePort);
status = freerdp_assistance_decrypt(file, TEST_MSRC_INCIDENT_PASSWORD_TYPE1);
printf("freerdp_assistance_decrypt: %d\n", status);
if (status < 0)
return -1;
pass = freerdp_assistance_bin_to_hex_string(file->EncryptedPassStub, file->EncryptedPassStubLength);
if (!pass)
return -1;
expertBlob = freerdp_assistance_construct_expert_blob("Edgar Olougouna", pass);
freerdp_assistance_file_free(file);
free(pass);
free(expertBlob);
return 0;
}
int test_msrsc_incident_file_type2()
{
int status;
rdpAssistanceFile* file;
file = freerdp_assistance_file_new();
status = freerdp_assistance_parse_file_buffer(file,
TEST_MSRC_INCIDENT_FILE_TYPE2, sizeof(TEST_MSRC_INCIDENT_FILE_TYPE2));
printf("freerdp_assistance_parse_file_buffer: %d\n", status);
if (status < 0)
return -1;
printf("Username: %s\n", file->Username);
printf("LHTicket: %s\n", file->LHTicket);
printf("RCTicket: %s\n", file->RCTicket);
printf("RCTicketEncrypted: %d\n", file->RCTicketEncrypted);
printf("PassStub: %s\n", file->PassStub);
printf("DtStart: %d\n", file->DtStart);
printf("DtLength: %d\n", file->DtLength);
printf("LowSpeed: %d\n", file->LowSpeed);
printf("RASessionId: %s\n", file->RASessionId);
printf("RASpecificParams: %s\n", file->RASpecificParams);
printf("MachineAddress: %s\n", file->MachineAddress);
printf("MachinePort: %d\n", (int) file->MachinePort);
status = freerdp_assistance_decrypt(file, TEST_MSRC_INCIDENT_PASSWORD_TYPE2);
printf("freerdp_assistance_decrypt: %d\n", status);
if (status < 0)
return -1;
printf("ConnectionString2: %s\n", file->ConnectionString2);
freerdp_assistance_file_free(file);
return 0;
}
int TestCommonAssistance(int argc, char* argv[])
{
test_msrsc_incident_file_type1();
test_msrsc_incident_file_type2();
return 0;
}

View File

@ -393,15 +393,15 @@ BOOL rdp_read_info_packet(wStream* s, rdpSettings* settings)
void rdp_write_info_packet(wStream* s, rdpSettings* settings)
{
UINT32 flags;
WCHAR* domain = NULL;
WCHAR* domainW = NULL;
int cbDomain = 0;
WCHAR* userName = NULL;
WCHAR* userNameW = NULL;
int cbUserName = 0;
WCHAR* password = NULL;
WCHAR* passwordW = NULL;
int cbPassword = 0;
WCHAR* alternateShell = NULL;
WCHAR* alternateShellW = NULL;
int cbAlternateShell = 0;
WCHAR* workingDir = NULL;
WCHAR* workingDirW = NULL;
int cbWorkingDir = 0;
BOOL usedPasswordCookie = FALSE;
@ -439,30 +439,62 @@ void rdp_write_info_packet(wStream* s, rdpSettings* settings)
if (settings->Domain)
{
cbDomain = ConvertToUnicode(CP_UTF8, 0, settings->Domain, -1, &domain, 0) * 2;
cbDomain = ConvertToUnicode(CP_UTF8, 0, settings->Domain, -1, &domainW, 0) * 2;
}
else
{
domain = NULL;
domainW = NULL;
cbDomain = 0;
}
cbUserName = ConvertToUnicode(CP_UTF8, 0, settings->Username, -1, &userName, 0) * 2;
if (settings->RedirectionPassword && settings->RedirectionPasswordLength > 0)
if (!settings->RemoteAssistanceMode)
{
usedPasswordCookie = TRUE;
password = (WCHAR*) settings->RedirectionPassword;
cbPassword = settings->RedirectionPasswordLength - 2; /* Strip double zero termination */
cbUserName = ConvertToUnicode(CP_UTF8, 0, settings->Username, -1, &userNameW, 0) * 2;
}
else
{
cbPassword = ConvertToUnicode(CP_UTF8, 0, settings->Password, -1, &password, 0) * 2;
/* user name provided by the expert for connecting to the novice computer */
cbUserName = ConvertToUnicode(CP_UTF8, 0, settings->Username, -1, &userNameW, 0) * 2;
}
cbAlternateShell = ConvertToUnicode(CP_UTF8, 0, settings->AlternateShell, -1, &alternateShell, 0) * 2;
if (!settings->RemoteAssistanceMode)
{
if (settings->RedirectionPassword && settings->RedirectionPasswordLength > 0)
{
usedPasswordCookie = TRUE;
passwordW = (WCHAR*) settings->RedirectionPassword;
cbPassword = settings->RedirectionPasswordLength - 2; /* Strip double zero termination */
}
else
{
cbPassword = ConvertToUnicode(CP_UTF8, 0, settings->Password, -1, &passwordW, 0) * 2;
}
}
else
{
/* This field MUST be filled with "*" */
cbPassword = ConvertToUnicode(CP_UTF8, 0, "*", -1, &passwordW, 0) * 2;
}
cbWorkingDir = ConvertToUnicode(CP_UTF8, 0, settings->ShellWorkingDirectory, -1, &workingDir, 0) * 2;
if (!settings->RemoteAssistanceMode)
{
cbAlternateShell = ConvertToUnicode(CP_UTF8, 0, settings->AlternateShell, -1, &alternateShellW, 0) * 2;
}
else
{
/* This field MUST be filled with "*" */
cbAlternateShell = ConvertToUnicode(CP_UTF8, 0, "*", -1, &alternateShellW, 0) * 2;
}
if (!settings->RemoteAssistanceMode)
{
cbWorkingDir = ConvertToUnicode(CP_UTF8, 0, settings->ShellWorkingDirectory, -1, &workingDirW, 0) * 2;
}
else
{
/* Remote Assistance Session Id */
cbWorkingDir = ConvertToUnicode(CP_UTF8, 0, settings->RemoteAssistanceSessionId, -1, &workingDirW, 0) * 2;
}
Stream_Write_UINT32(s, 0); /* CodePage */
Stream_Write_UINT32(s, flags); /* flags */
@ -474,32 +506,32 @@ void rdp_write_info_packet(wStream* s, rdpSettings* settings)
Stream_Write_UINT16(s, cbWorkingDir); /* cbWorkingDir */
if (cbDomain > 0)
Stream_Write(s, domain, cbDomain);
Stream_Write(s, domainW, cbDomain);
Stream_Write_UINT16(s, 0);
if (cbUserName > 0)
Stream_Write(s, userName, cbUserName);
Stream_Write(s, userNameW, cbUserName);
Stream_Write_UINT16(s, 0);
if (cbPassword > 0)
Stream_Write(s, password, cbPassword);
Stream_Write(s, passwordW, cbPassword);
Stream_Write_UINT16(s, 0);
if (cbAlternateShell > 0)
Stream_Write(s, alternateShell, cbAlternateShell);
Stream_Write(s, alternateShellW, cbAlternateShell);
Stream_Write_UINT16(s, 0);
if (cbWorkingDir > 0)
Stream_Write(s, workingDir, cbWorkingDir);
Stream_Write(s, workingDirW, cbWorkingDir);
Stream_Write_UINT16(s, 0);
free(domain);
free(userName);
free(alternateShell);
free(workingDir);
free(domainW);
free(userNameW);
free(alternateShellW);
free(workingDirW);
if (!usedPasswordCookie)
free(password);
free(passwordW);
if (settings->RdpVersion >= 5)
rdp_write_extended_info_packet(s, settings); /* extraInfo */

View File

@ -464,6 +464,10 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
_settings->ClientAddress = _strdup(settings->ClientAddress); /* 769 */
_settings->ClientDir = _strdup(settings->ClientDir); /* 770 */
_settings->DynamicDSTTimeZoneKeyName = _strdup(settings->DynamicDSTTimeZoneKeyName); /* 897 */
_settings->RemoteAssistanceSessionId = _strdup(settings->RemoteAssistanceSessionId); /* 1025 */
_settings->RemoteAssistancePassStub = _strdup(settings->RemoteAssistancePassStub); /* 1026 */
_settings->RemoteAssistancePassword = _strdup(settings->RemoteAssistancePassword); /* 1027 */
_settings->RemoteAssistanceRCTicket = _strdup(settings->RemoteAssistanceRCTicket); /* 1028 */
_settings->AuthenticationServiceClass = _strdup(settings->AuthenticationServiceClass); /* 1098 */
_settings->PreconnectionBlob = _strdup(settings->PreconnectionBlob); /* 1155 */
_settings->KerberosKdc = _strdup(settings->KerberosKdc); /* 1344 */
@ -476,6 +480,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
_settings->WmClass = _strdup(settings->WmClass); /* 1549 */
_settings->ComputerName = _strdup(settings->ComputerName); /* 1664 */
_settings->ConnectionFile = _strdup(settings->ConnectionFile); /* 1728 */
_settings->AssistanceFile = _strdup(settings->AssistanceFile); /* 1729 */
_settings->HomePath = _strdup(settings->HomePath); /* 1792 */
_settings->ConfigPath = _strdup(settings->ConfigPath); /* 1793 */
_settings->CurrentPath = _strdup(settings->CurrentPath); /* 1794 */
@ -624,6 +629,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
_settings->DisableCursorShadow = settings->DisableCursorShadow; /* 966 */
_settings->DisableCursorBlinking = settings->DisableCursorBlinking; /* 967 */
_settings->AllowDesktopComposition = settings->AllowDesktopComposition; /* 968 */
_settings->RemoteAssistanceMode = settings->RemoteAssistanceMode; /* 1024 */
_settings->TlsSecurity = settings->TlsSecurity; /* 1088 */
_settings->NlaSecurity = settings->NlaSecurity; /* 1089 */
_settings->RdpSecurity = settings->RdpSecurity; /* 1090 */
@ -810,6 +816,8 @@ void freerdp_settings_free(rdpSettings* settings)
free(settings->ClientDir);
free(settings->CertificateFile);
free(settings->PrivateKeyFile);
free(settings->ConnectionFile);
free(settings->AssistanceFile);
free(settings->ReceivedCapabilities);
free(settings->OrderSupport);
free(settings->ClientHostname);
@ -837,6 +845,7 @@ void freerdp_settings_free(rdpSettings* settings)
free(settings->RedirectionDomain);
free(settings->RedirectionPassword);
free(settings->RedirectionTsvUrl);
free(settings->RemoteAssistanceSessionId);
free(settings->AuthenticationServiceClass);
freerdp_target_net_addresses_free(settings);
freerdp_device_collection_free(settings);

View File

@ -24,7 +24,9 @@ set(${MODULE_PREFIX}_SRCS
sf_audin.c
sf_audin.h
sf_rdpsnd.c
sf_rdpsnd.h)
sf_rdpsnd.h
sf_encomsp.c
sf_encomsp.h)
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})

View File

@ -0,0 +1,37 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Sample Server (Lync Multiparty)
*
* Copyright 2014 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "sf_encomsp.h"
BOOL sf_peer_encomsp_init(testPeerContext* context)
{
context->encomsp = encomsp_server_context_new(context->vcm);
if (!context->encomsp)
return FALSE;
if (context->encomsp->Start(context->encomsp) < 0)
return FALSE;
return TRUE;
}

View File

@ -0,0 +1,31 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Sample Server (Lync Multiparty)
*
* Copyright 2014 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.
*/
#ifndef SF_ENCOMSP_H
#define SF_ENCOMSP_H
#include <freerdp/freerdp.h>
#include <freerdp/listener.h>
#include <freerdp/server/encomsp.h>
#include "sfreerdp.h"
BOOL sf_peer_encomsp_init(testPeerContext* context);
#endif /* SF_ENCOMSP_H */

View File

@ -52,7 +52,7 @@ BOOL sf_peer_rdpsnd_init(testPeerContext* context)
context->rdpsnd->Activated = sf_peer_rdpsnd_activated;
context->rdpsnd->Initialize(context->rdpsnd);
context->rdpsnd->Initialize(context->rdpsnd, TRUE);
return TRUE;
}

View File

@ -30,16 +30,17 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/channels/channels.h>
#include <freerdp/constants.h>
#include <freerdp/utils/tcp.h>
#include <freerdp/server/rdpsnd.h>
#include "sf_audin.h"
#include "sf_rdpsnd.h"
#include "sf_encomsp.h"
#include "sfreerdp.h"
@ -96,6 +97,9 @@ void test_peer_context_free(freerdp_peer* client, testPeerContext* context)
if (context->rdpsnd)
rdpsnd_server_context_free(context->rdpsnd);
if (context->encomsp)
encomsp_server_context_free(context->encomsp);
WTSCloseServer((HANDLE) context->vcm);
}
}
@ -516,6 +520,11 @@ BOOL tf_peer_post_connect(freerdp_peer* client)
sf_peer_rdpsnd_init(context); /* Audio Output */
}
if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "encomsp"))
{
sf_peer_encomsp_init(context); /* Lync Multiparty */
}
/* Dynamic Virtual Channels */
sf_peer_audin_init(context); /* Audio Input */

View File

@ -27,6 +27,7 @@
#include <freerdp/channels/wtsvc.h>
#include <freerdp/server/audin.h>
#include <freerdp/server/rdpsnd.h>
#include <freerdp/server/encomsp.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
@ -55,6 +56,7 @@ struct test_peer_context
BOOL audin_open;
UINT32 frame_id;
RdpsndServerContext* rdpsnd;
EncomspServerContext* encomsp;
};
typedef struct test_peer_context testPeerContext;