mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-27 03:44:06 +08:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
e4840d3596
1
.gitignore
vendored
1
.gitignore
vendored
@ -113,6 +113,7 @@ Release
|
||||
Win32
|
||||
build*/
|
||||
*.orig
|
||||
*.msrcIncident
|
||||
|
||||
default.log
|
||||
*Amplifier XE*
|
||||
|
@ -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;
|
||||
|
26
channels/encomsp/CMakeLists.txt
Normal file
26
channels/encomsp/CMakeLists.txt
Normal 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()
|
13
channels/encomsp/ChannelOptions.cmake
Normal file
13
channels/encomsp/ChannelOptions.cmake
Normal 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})
|
||||
|
35
channels/encomsp/client/CMakeLists.txt
Normal file
35
channels/encomsp/client/CMakeLists.txt
Normal 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")
|
948
channels/encomsp/client/encomsp_main.c
Normal file
948
channels/encomsp/client/encomsp_main.c
Normal 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;
|
||||
}
|
48
channels/encomsp/client/encomsp_main.h
Normal file
48
channels/encomsp/client/encomsp_main.h
Normal 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 */
|
37
channels/encomsp/server/CMakeLists.txt
Normal file
37
channels/encomsp/server/CMakeLists.txt
Normal 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")
|
157
channels/encomsp/server/encomsp_main.c
Normal file
157
channels/encomsp/server/encomsp_main.c
Normal 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);
|
||||
}
|
||||
}
|
36
channels/encomsp/server/encomsp_main.h
Normal file
36
channels/encomsp/server/encomsp_main.h
Normal 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 */
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
26
channels/remdesk/CMakeLists.txt
Normal file
26
channels/remdesk/CMakeLists.txt
Normal 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()
|
12
channels/remdesk/ChannelOptions.cmake
Normal file
12
channels/remdesk/ChannelOptions.cmake
Normal 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})
|
40
channels/remdesk/client/CMakeLists.txt
Normal file
40
channels/remdesk/client/CMakeLists.txt
Normal 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")
|
804
channels/remdesk/client/remdesk_main.c
Normal file
804
channels/remdesk/client/remdesk_main.c
Normal 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;
|
||||
}
|
55
channels/remdesk/client/remdesk_main.h
Normal file
55
channels/remdesk/client/remdesk_main.h
Normal 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 */
|
37
channels/remdesk/server/CMakeLists.txt
Normal file
37
channels/remdesk/server/CMakeLists.txt
Normal 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")
|
157
channels/remdesk/server/remdesk_main.c
Normal file
157
channels/remdesk/server/remdesk_main.c
Normal 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);
|
||||
}
|
||||
}
|
37
channels/remdesk/server/remdesk_main.h
Normal file
37
channels/remdesk/server/remdesk_main.h
Normal 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 */
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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})
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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.
|
||||
|
79
include/freerdp/assistance.h
Normal file
79
include/freerdp/assistance.h
Normal 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 */
|
||||
|
186
include/freerdp/channels/encomsp.h
Normal file
186
include/freerdp/channels/encomsp.h
Normal 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 */
|
||||
|
104
include/freerdp/channels/remdesk.h
Normal file
104
include/freerdp/channels/remdesk.h
Normal 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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
61
include/freerdp/client/encomsp.h
Normal file
61
include/freerdp/client/encomsp.h
Normal 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 */
|
38
include/freerdp/client/remdesk.h
Normal file
38
include/freerdp/client/remdesk.h
Normal 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 */
|
||||
|
52
include/freerdp/server/encomsp.h
Normal file
52
include/freerdp/server/encomsp.h
Normal 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 */
|
@ -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
|
||||
}
|
||||
|
53
include/freerdp/server/remdesk.h
Normal file
53
include/freerdp/server/remdesk.h
Normal 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 */
|
||||
|
@ -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 */
|
||||
|
@ -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()
|
||||
|
989
libfreerdp/common/assistance.c
Normal file
989
libfreerdp/common/assistance.c
Normal 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);
|
||||
}
|
@ -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
3
libfreerdp/common/test/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
TestCommon
|
||||
TestCommon.c
|
||||
|
31
libfreerdp/common/test/CMakeLists.txt
Normal file
31
libfreerdp/common/test/CMakeLists.txt
Normal 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")
|
||||
|
183
libfreerdp/common/test/TestCommonAssistance.c
Normal file
183
libfreerdp/common/test/TestCommonAssistance.c
Normal 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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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})
|
||||
|
||||
|
37
server/Sample/sf_encomsp.c
Normal file
37
server/Sample/sf_encomsp.c
Normal 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;
|
||||
}
|
31
server/Sample/sf_encomsp.h
Normal file
31
server/Sample/sf_encomsp.h
Normal 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 */
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user