Merge branch 'master' of git://github.com/awakecoding/FreeRDP
# By Bernhard Miklautz (10) and others # Via Marc-André Moreau (10) and Martin Fleisz (1) * 'master' of git://github.com/awakecoding/FreeRDP: (32 commits) libfreerdp-crypto: add robustness checks for VerifyX509Certificate mfreerdp: fix possible crash on gdi termination channels/cliprdr: add callback for data request response channels/cliprdr: fix conflict with CLIPRDR_HEADER fix a gdi leak bug. channels/cliprdr: implement more of the callback interface channels/cliprdr: start implementing clean callback interface channels/rdpsnd: initial attempt at adding GSM610 support winpr-thread: fixed bugs in _CreateProcessExA ffmpeg-2 -- CodecID ffmpeg-2 -- dsp_mask ffmpeg-2 -- AVCODEC_MAX_AUDIO_FRAME_SIZE check return value. reformat coding styles. fix name length to copy. fix memory realloc size error. libfreerdp-crypto: don't report SSL_ERROR_SYSCALL with errno value 0 as error channels/rdpsnd: add wlog debug output android toolchain: support for ndk r9b android toolchain: fixed cmake syntax warning ...
This commit is contained in:
commit
6a60f79e07
@ -68,11 +68,11 @@ endif()
|
||||
|
||||
# Allow to search the host machine for git
|
||||
if(ANDROID OR IOS)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, BOTH)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
|
||||
endif(ANDROID OR IOS)
|
||||
include(GetGitRevisionDescription)
|
||||
if(ANDROID OR IOS)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
|
||||
endif(ANDROID OR IOS)
|
||||
|
||||
git_describe(GIT_REVISION --match "[0-9]*" --abbrev=4 --tags --always)
|
||||
@ -301,8 +301,9 @@ endif()
|
||||
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/client/Android/FreeRDPCore/jni/${ANDROID_ABI})
|
||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/regenerate_jni_headers.sh.cmake
|
||||
${CMAKE_BINARY_DIR}/scripts/regenerate_jni_headers.sh @ONLY)
|
||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/gprof_generate.sh.cmake
|
||||
${CMAKE_BINARY_DIR}/scripts/gprof_generate.sh @ONLY)
|
||||
if (WITH_GPROF)
|
||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/gprof_generate.sh.cmake ${CMAKE_BINARY_DIR}/scripts/gprof_generate.sh @ONLY)
|
||||
endif(WITH_GPROF)
|
||||
|
||||
endif()
|
||||
|
||||
@ -381,6 +382,10 @@ set(JPEG_FEATURE_TYPE "OPTIONAL")
|
||||
set(JPEG_FEATURE_PURPOSE "codec")
|
||||
set(JPEG_FEATURE_DESCRIPTION "use JPEG library")
|
||||
|
||||
set(GSM_FEATURE_TYPE "OPTIONAL")
|
||||
set(GSM_FEATURE_PURPOSE "codec")
|
||||
set(GSM_FEATURE_DESCRIPTION "GSM audio codec library")
|
||||
|
||||
if(WIN32)
|
||||
set(X11_FEATURE_TYPE "DISABLED")
|
||||
set(ZLIB_FEATURE_TYPE "DISABLED")
|
||||
@ -445,6 +450,7 @@ find_feature(FFmpeg ${FFMPEG_FEATURE_TYPE} ${FFMPEG_FEATURE_PURPOSE} ${FFMPEG_FE
|
||||
find_feature(Gstreamer ${GSTREAMER_FEATURE_TYPE} ${GSTREAMER_FEATURE_PURPOSE} ${GSTREAMER_FEATURE_DESCRIPTION})
|
||||
|
||||
find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DESCRIPTION})
|
||||
find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION})
|
||||
|
||||
if(TARGET_ARCH MATCHES "x86|x64")
|
||||
if (NOT APPLE)
|
||||
|
@ -213,120 +213,223 @@ void cliprdr_process_long_format_names(cliprdrPlugin* cliprdr, wStream* s, UINT3
|
||||
|
||||
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
||||
{
|
||||
int i;
|
||||
UINT32 format;
|
||||
BOOL supported;
|
||||
CLIPRDR_FORMAT_NAME* format_name;
|
||||
RDP_CB_FORMAT_LIST_EVENT* cb_event;
|
||||
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||
|
||||
cb_event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
|
||||
CliprdrChannel_FormatList, NULL, NULL);
|
||||
|
||||
if (dataLen > 0)
|
||||
if (context->custom)
|
||||
{
|
||||
cb_event->raw_format_data = (BYTE*) malloc(dataLen);
|
||||
memcpy(cb_event->raw_format_data, Stream_Pointer(s), dataLen);
|
||||
cb_event->raw_format_data_size = dataLen;
|
||||
cb_event->raw_format_unicode = (msgFlags & CB_ASCII_NAMES) ? FALSE : TRUE;
|
||||
}
|
||||
int index;
|
||||
int formatNameLength;
|
||||
CLIPRDR_FORMAT* formats;
|
||||
CLIPRDR_FORMAT_LIST formatList;
|
||||
|
||||
if (cliprdr->use_long_format_names)
|
||||
cliprdr_process_long_format_names(cliprdr, s, dataLen, msgFlags);
|
||||
else
|
||||
cliprdr_process_short_format_names(cliprdr, s, dataLen, msgFlags);
|
||||
formatList.msgType = CB_FORMAT_LIST;
|
||||
formatList.msgFlags = msgFlags;
|
||||
formatList.dataLen = dataLen;
|
||||
|
||||
if (cliprdr->num_format_names > 0)
|
||||
cb_event->formats = (UINT32*) malloc(sizeof(UINT32) * cliprdr->num_format_names);
|
||||
formatList.cFormats = 0;
|
||||
|
||||
cb_event->num_formats = 0;
|
||||
|
||||
for (i = 0; i < cliprdr->num_format_names; i++)
|
||||
{
|
||||
supported = TRUE;
|
||||
format_name = &cliprdr->format_names[i];
|
||||
format = format_name->id;
|
||||
|
||||
switch (format)
|
||||
while (dataLen)
|
||||
{
|
||||
case CB_FORMAT_TEXT:
|
||||
case CB_FORMAT_DIB:
|
||||
case CB_FORMAT_UNICODETEXT:
|
||||
break;
|
||||
Stream_Seek(s, 4); /* formatId */
|
||||
dataLen -= 4;
|
||||
|
||||
default:
|
||||
|
||||
if (format_name->length > 0)
|
||||
{
|
||||
DEBUG_CLIPRDR("format: %s", format_name->name);
|
||||
|
||||
if (strcmp(format_name->name, "HTML Format") == 0)
|
||||
{
|
||||
format = CB_FORMAT_HTML;
|
||||
break;
|
||||
}
|
||||
if (strcmp(format_name->name, "PNG") == 0)
|
||||
{
|
||||
format = CB_FORMAT_PNG;
|
||||
break;
|
||||
}
|
||||
if (strcmp(format_name->name, "JFIF") == 0)
|
||||
{
|
||||
format = CB_FORMAT_JPEG;
|
||||
break;
|
||||
}
|
||||
if (strcmp(format_name->name, "GIF") == 0)
|
||||
{
|
||||
format = CB_FORMAT_GIF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
supported = FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s));
|
||||
Stream_Seek(s, (formatNameLength + 1) * 2);
|
||||
dataLen -= ((formatNameLength + 1) * 2);
|
||||
formatList.cFormats++;
|
||||
}
|
||||
|
||||
if (supported)
|
||||
cb_event->formats[cb_event->num_formats++] = format;
|
||||
index = 0;
|
||||
dataLen = formatList.dataLen;
|
||||
Stream_Rewind(s, dataLen);
|
||||
|
||||
if (format_name->length > 0)
|
||||
free(format_name->name);
|
||||
formats = (CLIPRDR_FORMAT*) malloc(sizeof(CLIPRDR_FORMAT) * formatList.cFormats);
|
||||
formatList.formats = formats;
|
||||
|
||||
while (dataLen)
|
||||
{
|
||||
Stream_Read_UINT32(s, formats[index].formatId); /* formatId */
|
||||
dataLen -= 4;
|
||||
|
||||
formats[index].formatName = NULL;
|
||||
formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s));
|
||||
|
||||
if (formatNameLength)
|
||||
{
|
||||
formatNameLength = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
|
||||
-1, &(formats[index].formatName), 0, NULL, NULL);
|
||||
|
||||
Stream_Seek(s, formatNameLength * 2);
|
||||
dataLen -= (formatNameLength * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream_Seek(s, 2);
|
||||
dataLen -= 2;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (context->ServerFormatList)
|
||||
context->ServerFormatList(context, &formatList);
|
||||
|
||||
for (index = 0; index < formatList.cFormats; index++)
|
||||
free(formats[index].formatName);
|
||||
|
||||
free(formats);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
UINT32 format;
|
||||
BOOL supported;
|
||||
CLIPRDR_FORMAT_NAME* format_name;
|
||||
RDP_CB_FORMAT_LIST_EVENT* cb_event;
|
||||
|
||||
free(cliprdr->format_names);
|
||||
cliprdr->format_names = NULL;
|
||||
cb_event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
|
||||
CliprdrChannel_FormatList, NULL, NULL);
|
||||
|
||||
cliprdr->num_format_names = 0;
|
||||
if (dataLen > 0)
|
||||
{
|
||||
cb_event->raw_format_data = (BYTE*) malloc(dataLen);
|
||||
memcpy(cb_event->raw_format_data, Stream_Pointer(s), dataLen);
|
||||
cb_event->raw_format_data_size = dataLen;
|
||||
cb_event->raw_format_unicode = (msgFlags & CB_ASCII_NAMES) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
||||
cliprdr_send_format_list_response(cliprdr);
|
||||
if (cliprdr->use_long_format_names)
|
||||
cliprdr_process_long_format_names(cliprdr, s, dataLen, msgFlags);
|
||||
else
|
||||
cliprdr_process_short_format_names(cliprdr, s, dataLen, msgFlags);
|
||||
|
||||
if (cliprdr->num_format_names > 0)
|
||||
cb_event->formats = (UINT32*) malloc(sizeof(UINT32) * cliprdr->num_format_names);
|
||||
|
||||
cb_event->num_formats = 0;
|
||||
|
||||
for (i = 0; i < cliprdr->num_format_names; i++)
|
||||
{
|
||||
supported = TRUE;
|
||||
format_name = &cliprdr->format_names[i];
|
||||
format = format_name->id;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case CB_FORMAT_TEXT:
|
||||
case CB_FORMAT_DIB:
|
||||
case CB_FORMAT_UNICODETEXT:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (format_name->length > 0)
|
||||
{
|
||||
DEBUG_CLIPRDR("format: %s", format_name->name);
|
||||
|
||||
if (strcmp(format_name->name, "HTML Format") == 0)
|
||||
{
|
||||
format = CB_FORMAT_HTML;
|
||||
break;
|
||||
}
|
||||
if (strcmp(format_name->name, "PNG") == 0)
|
||||
{
|
||||
format = CB_FORMAT_PNG;
|
||||
break;
|
||||
}
|
||||
if (strcmp(format_name->name, "JFIF") == 0)
|
||||
{
|
||||
format = CB_FORMAT_JPEG;
|
||||
break;
|
||||
}
|
||||
if (strcmp(format_name->name, "GIF") == 0)
|
||||
{
|
||||
format = CB_FORMAT_GIF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
supported = FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (supported)
|
||||
cb_event->formats[cb_event->num_formats++] = format;
|
||||
|
||||
if (format_name->length > 0)
|
||||
free(format_name->name);
|
||||
}
|
||||
|
||||
free(cliprdr->format_names);
|
||||
cliprdr->format_names = NULL;
|
||||
|
||||
cliprdr->num_format_names = 0;
|
||||
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
||||
cliprdr_send_format_list_response(cliprdr);
|
||||
}
|
||||
}
|
||||
|
||||
void cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
||||
{
|
||||
/* http://msdn.microsoft.com/en-us/library/hh872154.aspx */
|
||||
wMessage* event;
|
||||
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||
|
||||
if ((msgFlags & CB_RESPONSE_FAIL) != 0)
|
||||
/* http://msdn.microsoft.com/en-us/library/hh872154.aspx */
|
||||
|
||||
if (context->custom)
|
||||
{
|
||||
/* In case of an error the clipboard will not be synchronized with the server.
|
||||
* Post this event to restart format negociation and data transfer. */
|
||||
event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event);
|
||||
CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse;
|
||||
|
||||
formatListResponse.msgType = CB_FORMAT_LIST_RESPONSE;
|
||||
formatListResponse.msgFlags = msgFlags;
|
||||
formatListResponse.dataLen = dataLen;
|
||||
|
||||
if (context->ServerFormatListResponse)
|
||||
context->ServerFormatListResponse(context, &formatListResponse);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((msgFlags & CB_RESPONSE_FAIL) != 0)
|
||||
{
|
||||
/* In case of an error the clipboard will not be synchronized with the server.
|
||||
* Post this event to restart format negotiation and data transfer. */
|
||||
|
||||
wMessage* event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
||||
{
|
||||
RDP_CB_DATA_REQUEST_EVENT* cb_event;
|
||||
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||
|
||||
cb_event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
|
||||
CliprdrChannel_DataRequest, NULL, NULL);
|
||||
if (context->custom)
|
||||
{
|
||||
CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest;
|
||||
|
||||
Stream_Read_UINT32(s, cb_event->format);
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
||||
formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST;
|
||||
formatDataRequest.msgFlags = msgFlags;
|
||||
formatDataRequest.dataLen = dataLen;
|
||||
|
||||
Stream_Read_UINT32(s, formatDataRequest.requestedFormatId); /* requestedFormatId (4 bytes) */
|
||||
|
||||
if (context->ServerFormatDataRequest)
|
||||
context->ServerFormatDataRequest(context, &formatDataRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDP_CB_DATA_REQUEST_EVENT* cb_event;
|
||||
|
||||
cb_event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class,
|
||||
CliprdrChannel_DataRequest, NULL, NULL);
|
||||
|
||||
Stream_Read_UINT32(s, cb_event->format);
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
||||
}
|
||||
}
|
||||
|
||||
void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_RESPONSE_EVENT* cb_event)
|
||||
@ -361,17 +464,42 @@ void cliprdr_process_format_data_request_event(cliprdrPlugin* cliprdr, RDP_CB_DA
|
||||
|
||||
void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
|
||||
{
|
||||
RDP_CB_DATA_RESPONSE_EVENT* cb_event;
|
||||
|
||||
cb_event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class,
|
||||
CliprdrChannel_DataResponse, NULL, NULL);
|
||||
|
||||
if (dataLen > 0)
|
||||
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||
|
||||
if (context->custom)
|
||||
{
|
||||
cb_event->size = dataLen;
|
||||
cb_event->data = (BYTE*) malloc(dataLen);
|
||||
CopyMemory(cb_event->data, Stream_Pointer(s), dataLen);
|
||||
CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse;
|
||||
|
||||
formatDataResponse.msgType = CB_FORMAT_DATA_RESPONSE;
|
||||
formatDataResponse.msgFlags = msgFlags;
|
||||
formatDataResponse.dataLen = dataLen;
|
||||
formatDataResponse.requestedFormatData = NULL;
|
||||
|
||||
if (dataLen)
|
||||
{
|
||||
formatDataResponse.requestedFormatData = (BYTE*) malloc(dataLen);
|
||||
Stream_Read(s, formatDataResponse.requestedFormatData, dataLen);
|
||||
}
|
||||
|
||||
if (context->ClientFormatDataResponse)
|
||||
context->ClientFormatDataResponse(context, &formatDataResponse);
|
||||
|
||||
free(formatDataResponse.requestedFormatData);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDP_CB_DATA_RESPONSE_EVENT* cb_event;
|
||||
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
||||
cb_event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class,
|
||||
CliprdrChannel_DataResponse, NULL, NULL);
|
||||
|
||||
if (dataLen > 0)
|
||||
{
|
||||
cb_event->size = dataLen;
|
||||
cb_event->data = (BYTE*) malloc(dataLen);
|
||||
CopyMemory(cb_event->data, Stream_Pointer(s), dataLen);
|
||||
}
|
||||
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,14 @@ static const char* const CB_MSG_TYPE_STRINGS[] =
|
||||
"CB_UNLOCK_CLIPDATA"
|
||||
};
|
||||
|
||||
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr)
|
||||
{
|
||||
CliprdrClientContext* pInterface;
|
||||
rdpSvcPlugin* plugin = (rdpSvcPlugin*) cliprdr;
|
||||
pInterface = (CliprdrClientContext*) *(plugin->channel_entry_points.ppInterface);
|
||||
return pInterface;
|
||||
}
|
||||
|
||||
wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen)
|
||||
{
|
||||
wStream* s;
|
||||
@ -110,7 +118,9 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
|
||||
{
|
||||
UINT32 version;
|
||||
UINT32 generalFlags;
|
||||
RDP_CB_CLIP_CAPS *caps_event;
|
||||
CliprdrClientContext* context;
|
||||
|
||||
context = cliprdr_get_client_interface(cliprdr);
|
||||
|
||||
Stream_Read_UINT32(s, version); /* version (4 bytes) */
|
||||
Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
|
||||
@ -121,9 +131,6 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
|
||||
cliprdr_print_general_capability_flags(generalFlags);
|
||||
#endif
|
||||
|
||||
caps_event = (RDP_CB_CLIP_CAPS *)freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_ClipCaps, NULL, NULL);
|
||||
caps_event->capabilities = generalFlags;
|
||||
|
||||
if (generalFlags & CB_USE_LONG_FORMAT_NAMES)
|
||||
cliprdr->use_long_format_names = TRUE;
|
||||
|
||||
@ -138,8 +145,32 @@ static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
|
||||
|
||||
cliprdr->received_caps = TRUE;
|
||||
|
||||
svc_plugin_send_event((rdpSvcPlugin *)cliprdr, (wMessage *)caps_event);
|
||||
if (context->custom)
|
||||
{
|
||||
CLIPRDR_CAPABILITIES capabilities;
|
||||
CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
|
||||
|
||||
capabilities.cCapabilitiesSets = 1;
|
||||
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet);
|
||||
|
||||
generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
|
||||
generalCapabilitySet.capabilitySetLength = 12;
|
||||
|
||||
generalCapabilitySet.version = version;
|
||||
generalCapabilitySet.generalFlags = generalFlags;
|
||||
|
||||
if (context->ServerCapabilities)
|
||||
context->ServerCapabilities(context, &capabilities);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDP_CB_CLIP_CAPS* caps_event;
|
||||
|
||||
caps_event = (RDP_CB_CLIP_CAPS*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_ClipCaps, NULL, NULL);
|
||||
caps_event->capabilities = generalFlags;
|
||||
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) caps_event);
|
||||
}
|
||||
}
|
||||
|
||||
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
|
||||
@ -195,14 +226,30 @@ static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr)
|
||||
|
||||
static void cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags)
|
||||
{
|
||||
RDP_CB_MONITOR_READY_EVENT* event;
|
||||
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
|
||||
|
||||
if (cliprdr->received_caps)
|
||||
cliprdr_send_clip_caps(cliprdr);
|
||||
if (context->custom)
|
||||
{
|
||||
CLIPRDR_MONITOR_READY monitorReady;
|
||||
|
||||
event = (RDP_CB_MONITOR_READY_EVENT *)freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
|
||||
monitorReady.msgType = CB_MONITOR_READY;
|
||||
monitorReady.msgFlags = flags;
|
||||
monitorReady.dataLen = length;
|
||||
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage *)event);
|
||||
if (context->MonitorReady)
|
||||
context->MonitorReady(context, &monitorReady);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDP_CB_MONITOR_READY_EVENT* event;
|
||||
|
||||
if (cliprdr->received_caps)
|
||||
cliprdr_send_clip_caps(cliprdr);
|
||||
|
||||
event = (RDP_CB_MONITOR_READY_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
|
||||
|
||||
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) event);
|
||||
}
|
||||
}
|
||||
|
||||
static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s)
|
||||
@ -218,7 +265,7 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s)
|
||||
|
||||
DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d",
|
||||
CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen);
|
||||
|
||||
|
||||
#ifdef WITH_DEBUG_CLIPRDR
|
||||
winpr_HexDump(Stream_Buffer(s), dataLen + 8);
|
||||
#endif
|
||||
@ -290,23 +337,127 @@ static void cliprdr_process_terminate(rdpSvcPlugin* plugin)
|
||||
* Callback Interface
|
||||
*/
|
||||
|
||||
int cliprdr_monitor_ready(CliprdrClientContext* context)
|
||||
int cliprdr_client_capabilities(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities)
|
||||
{
|
||||
wStream* s;
|
||||
CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
|
||||
s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
|
||||
|
||||
Stream_Write_UINT16(s, 1); /* cCapabilitiesSets */
|
||||
Stream_Write_UINT16(s, 0); /* pad1 */
|
||||
|
||||
generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*) capabilities->capabilitySets;
|
||||
|
||||
Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetType); /* capabilitySetType */
|
||||
Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetLength); /* lengthCapability */
|
||||
Stream_Write_UINT32(s, generalCapabilitySet->version); /* version */
|
||||
Stream_Write_UINT32(s, generalCapabilitySet->generalFlags); /* generalFlags */
|
||||
|
||||
cliprdr_packet_send(cliprdr, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cliprdr_format_list(CliprdrClientContext* context)
|
||||
int cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList)
|
||||
{
|
||||
int index;
|
||||
wStream* s;
|
||||
int length = 0;
|
||||
int formatNameSize;
|
||||
CLIPRDR_FORMAT* format;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
|
||||
for (index = 0; index < formatList->cFormats; index++)
|
||||
{
|
||||
format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);
|
||||
|
||||
length += 4;
|
||||
|
||||
formatNameSize = 2;
|
||||
|
||||
if (format->formatName)
|
||||
formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, 0) * 2;
|
||||
|
||||
length += formatNameSize;
|
||||
}
|
||||
|
||||
s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length);
|
||||
|
||||
for (index = 0; index < formatList->cFormats; index++)
|
||||
{
|
||||
format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);
|
||||
|
||||
Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */
|
||||
|
||||
if (format->formatName)
|
||||
{
|
||||
int cchWideChar;
|
||||
LPWSTR lpWideCharStr;
|
||||
|
||||
lpWideCharStr = (LPWSTR) Stream_Pointer(s);
|
||||
cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2;
|
||||
|
||||
formatNameSize = MultiByteToWideChar(CP_UTF8, 0,
|
||||
format->formatName, -1, lpWideCharStr, cchWideChar) * 2;
|
||||
|
||||
Stream_Seek(s, formatNameSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
Stream_Write_UINT16(s, 0);
|
||||
}
|
||||
}
|
||||
|
||||
cliprdr_packet_send(cliprdr, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cliprdr_data_request(CliprdrClientContext* context)
|
||||
int cliprdr_client_format_list_response(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
|
||||
{
|
||||
wStream* s;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
|
||||
formatListResponse->msgType = CB_FORMAT_LIST_RESPONSE;
|
||||
formatListResponse->dataLen = 0;
|
||||
|
||||
s = cliprdr_packet_new(formatListResponse->msgType, formatListResponse->msgFlags, formatListResponse->dataLen);
|
||||
cliprdr_packet_send(cliprdr, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cliprdr_data_response(CliprdrClientContext* context)
|
||||
int cliprdr_client_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
{
|
||||
wStream* s;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
|
||||
formatDataRequest->msgType = CB_FORMAT_DATA_REQUEST;
|
||||
formatDataRequest->msgFlags = 0;
|
||||
formatDataRequest->dataLen = 4;
|
||||
|
||||
s = cliprdr_packet_new(formatDataRequest->msgType, formatDataRequest->msgFlags, formatDataRequest->dataLen);
|
||||
Stream_Write_UINT32(s, formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */
|
||||
|
||||
cliprdr_packet_send(cliprdr, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cliprdr_client_format_data_response(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
|
||||
{
|
||||
wStream* s;
|
||||
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
|
||||
|
||||
formatDataResponse->msgType = CB_FORMAT_DATA_RESPONSE;
|
||||
|
||||
s = cliprdr_packet_new(formatDataResponse->msgType, formatDataResponse->msgFlags, formatDataResponse->dataLen);
|
||||
Stream_Write(s, formatDataResponse->requestedFormatData, formatDataResponse->dataLen);
|
||||
|
||||
cliprdr_packet_send(cliprdr, s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -315,25 +466,25 @@ int cliprdr_data_response(CliprdrClientContext* context)
|
||||
|
||||
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
cliprdrPlugin* _p;
|
||||
cliprdrPlugin* cliprdr;
|
||||
CliprdrClientContext* context;
|
||||
CHANNEL_ENTRY_POINTS_EX* pEntryPointsEx;
|
||||
|
||||
_p = (cliprdrPlugin*) malloc(sizeof(cliprdrPlugin));
|
||||
ZeroMemory(_p, sizeof(cliprdrPlugin));
|
||||
cliprdr = (cliprdrPlugin*) malloc(sizeof(cliprdrPlugin));
|
||||
ZeroMemory(cliprdr, sizeof(cliprdrPlugin));
|
||||
|
||||
_p->plugin.channel_def.options =
|
||||
cliprdr->plugin.channel_def.options =
|
||||
CHANNEL_OPTION_INITIALIZED |
|
||||
CHANNEL_OPTION_ENCRYPT_RDP |
|
||||
CHANNEL_OPTION_COMPRESS_RDP |
|
||||
CHANNEL_OPTION_SHOW_PROTOCOL;
|
||||
|
||||
strcpy(_p->plugin.channel_def.name, "cliprdr");
|
||||
strcpy(cliprdr->plugin.channel_def.name, "cliprdr");
|
||||
|
||||
_p->plugin.connect_callback = cliprdr_process_connect;
|
||||
_p->plugin.receive_callback = cliprdr_process_receive;
|
||||
_p->plugin.event_callback = cliprdr_process_event;
|
||||
_p->plugin.terminate_callback = cliprdr_process_terminate;
|
||||
cliprdr->plugin.connect_callback = cliprdr_process_connect;
|
||||
cliprdr->plugin.receive_callback = cliprdr_process_receive;
|
||||
cliprdr->plugin.event_callback = cliprdr_process_event;
|
||||
cliprdr->plugin.terminate_callback = cliprdr_process_terminate;
|
||||
|
||||
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_EX*) pEntryPoints;
|
||||
|
||||
@ -341,16 +492,20 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
|
||||
{
|
||||
context = (CliprdrClientContext*) malloc(sizeof(CliprdrClientContext));
|
||||
ZeroMemory(context, sizeof(CliprdrClientContext));
|
||||
|
||||
context->MonitorReady = cliprdr_monitor_ready;
|
||||
context->FormatList = cliprdr_format_list;
|
||||
context->DataRequest = cliprdr_data_request;
|
||||
context->DataResponse = cliprdr_data_response;
|
||||
context->handle = (void*) cliprdr;
|
||||
|
||||
context->ClientCapabilities = cliprdr_client_capabilities;
|
||||
context->ClientFormatList = cliprdr_client_format_list;
|
||||
context->ClientFormatListResponse = cliprdr_client_format_list_response;
|
||||
context->ClientFormatDataRequest = cliprdr_client_format_data_request;
|
||||
context->ClientFormatDataResponse = cliprdr_client_format_data_response;
|
||||
|
||||
*(pEntryPointsEx->ppInterface) = (void*) context;
|
||||
}
|
||||
|
||||
svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints);
|
||||
svc_plugin_init((rdpSvcPlugin*) cliprdr, pEntryPoints);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ typedef struct cliprdr_plugin cliprdrPlugin;
|
||||
wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen);
|
||||
void cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* data_out);
|
||||
|
||||
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr);
|
||||
|
||||
#ifdef WITH_DEBUG_CLIPRDR
|
||||
#define DEBUG_CLIPRDR(fmt, ...) DEBUG_CLASS(CLIPRDR, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
|
@ -28,14 +28,6 @@
|
||||
|
||||
#define CLIPRDR_HEADER_LENGTH 8
|
||||
|
||||
struct _CLIPRDR_HEADER
|
||||
{
|
||||
UINT16 msgType;
|
||||
UINT16 msgFlags;
|
||||
UINT32 dataLen;
|
||||
};
|
||||
typedef struct _CLIPRDR_HEADER CLIPRDR_HEADER;
|
||||
|
||||
struct _cliprdr_server_private
|
||||
{
|
||||
HANDLE Thread;
|
||||
|
@ -32,7 +32,11 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MODULE freerdp
|
||||
MODULES freerdp-codec freerdp-utils)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
|
||||
list(APPEND ${MODULE_PREFIX}_LIBS ${PULSE_LIBRARY})
|
||||
|
||||
if(GSM_FOUND)
|
||||
list(APPEND ${MODULE_PREFIX}_LIBS ${GSM_LIBRARIES})
|
||||
endif()
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
@ -26,10 +26,15 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
|
||||
#ifdef WITH_GSM
|
||||
#include <gsm/gsm.h>
|
||||
#endif
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/codec/dsp.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
@ -52,6 +57,11 @@ struct rdpsnd_pulse_plugin
|
||||
int latency;
|
||||
|
||||
FREERDP_DSP_CONTEXT* dsp_context;
|
||||
|
||||
#ifdef WITH_GSM
|
||||
gsm gsm_context;
|
||||
wStream* gsmBuffer;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void rdpsnd_pulse_context_state_callback(pa_context* context, void* userdata)
|
||||
@ -241,6 +251,7 @@ static void rdpsnd_pulse_set_format_spec(rdpsndPulsePlugin* pulse, AUDIO_FORMAT*
|
||||
break;
|
||||
|
||||
case WAVE_FORMAT_GSM610:
|
||||
sample_spec.format = PA_SAMPLE_S16LE;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -331,6 +342,14 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
|
||||
if (state == PA_STREAM_READY)
|
||||
{
|
||||
freerdp_dsp_context_reset_adpcm(pulse->dsp_context);
|
||||
|
||||
#ifdef WITH_GSM
|
||||
if (pulse->gsm_context)
|
||||
gsm_destroy(pulse->gsm_context);
|
||||
|
||||
pulse->gsm_context = gsm_create();
|
||||
#endif
|
||||
|
||||
DEBUG_SVC("connected");
|
||||
}
|
||||
else
|
||||
@ -410,7 +429,18 @@ static BOOL rdpsnd_pulse_format_supported(rdpsndDevicePlugin* device, AUDIO_FORM
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef WITH_GSM
|
||||
case WAVE_FORMAT_GSM610:
|
||||
if ((format->nSamplesPerSec <= PA_RATE_MAX) &&
|
||||
(format->nBlockAlign == 65) && (format->nChannels == 1))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -459,63 +489,108 @@ static void rdpsnd_pulse_set_volume(rdpsndDevicePlugin* device, UINT32 value)
|
||||
pa_threaded_mainloop_unlock(pulse->mainloop);
|
||||
}
|
||||
|
||||
static BYTE* rdpsnd_pulse_convert_audio(rdpsndDevicePlugin* device, BYTE* data, int* size)
|
||||
{
|
||||
BYTE* pcmData = NULL;
|
||||
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device;
|
||||
|
||||
if (pulse->format == WAVE_FORMAT_ADPCM)
|
||||
{
|
||||
pulse->dsp_context->decode_ms_adpcm(pulse->dsp_context,
|
||||
data, *size, pulse->sample_spec.channels, pulse->block_size);
|
||||
|
||||
*size = pulse->dsp_context->adpcm_size;
|
||||
pcmData = pulse->dsp_context->adpcm_buffer;
|
||||
}
|
||||
else if (pulse->format == WAVE_FORMAT_DVI_ADPCM)
|
||||
{
|
||||
pulse->dsp_context->decode_ima_adpcm(pulse->dsp_context,
|
||||
data, *size, pulse->sample_spec.channels, pulse->block_size);
|
||||
|
||||
*size = pulse->dsp_context->adpcm_size;
|
||||
pcmData = pulse->dsp_context->adpcm_buffer;
|
||||
}
|
||||
#ifdef WITH_GSM
|
||||
else if (pulse->format == WAVE_FORMAT_GSM610)
|
||||
{
|
||||
int inPos = 0;
|
||||
int inSize = *size;
|
||||
UINT16 gsmBlockBuffer[160];
|
||||
|
||||
Stream_SetPosition(pulse->gsmBuffer, 0);
|
||||
|
||||
while (inSize)
|
||||
{
|
||||
ZeroMemory(gsmBlockBuffer, sizeof(gsmBlockBuffer));
|
||||
gsm_decode(pulse->gsm_context, (gsm_byte*) &data[inPos], (gsm_signal*) gsmBlockBuffer);
|
||||
|
||||
if ((inPos % 65) == 0)
|
||||
{
|
||||
inPos += 33;
|
||||
inSize -= 33;
|
||||
}
|
||||
else
|
||||
{
|
||||
inPos += 32;
|
||||
inSize -= 32;
|
||||
}
|
||||
|
||||
Stream_EnsureRemainingCapacity(pulse->gsmBuffer, 160 * 2);
|
||||
Stream_Write(pulse->gsmBuffer, (void*) gsmBlockBuffer, 160 * 2);
|
||||
}
|
||||
|
||||
Stream_SealLength(pulse->gsmBuffer);
|
||||
|
||||
pcmData = Stream_Buffer(pulse->gsmBuffer);
|
||||
*size = Stream_Length(pulse->gsmBuffer);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
pcmData = data;
|
||||
}
|
||||
|
||||
return pcmData;
|
||||
}
|
||||
|
||||
static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, BYTE* data, int size)
|
||||
{
|
||||
int len;
|
||||
int ret;
|
||||
BYTE* src;
|
||||
int length;
|
||||
int status;
|
||||
BYTE* pcmData;
|
||||
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device;
|
||||
|
||||
if (!pulse->stream)
|
||||
return;
|
||||
|
||||
if (pulse->format == WAVE_FORMAT_ADPCM)
|
||||
{
|
||||
pulse->dsp_context->decode_ms_adpcm(pulse->dsp_context,
|
||||
data, size, pulse->sample_spec.channels, pulse->block_size);
|
||||
|
||||
size = pulse->dsp_context->adpcm_size;
|
||||
src = pulse->dsp_context->adpcm_buffer;
|
||||
}
|
||||
else if (pulse->format == WAVE_FORMAT_DVI_ADPCM)
|
||||
{
|
||||
pulse->dsp_context->decode_ima_adpcm(pulse->dsp_context,
|
||||
data, size, pulse->sample_spec.channels, pulse->block_size);
|
||||
|
||||
size = pulse->dsp_context->adpcm_size;
|
||||
src = pulse->dsp_context->adpcm_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
src = data;
|
||||
}
|
||||
pcmData = rdpsnd_pulse_convert_audio(device, data, &size);
|
||||
|
||||
pa_threaded_mainloop_lock(pulse->mainloop);
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
while ((len = pa_stream_writable_size(pulse->stream)) == 0)
|
||||
while ((length = pa_stream_writable_size(pulse->stream)) == 0)
|
||||
{
|
||||
pa_threaded_mainloop_wait(pulse->mainloop);
|
||||
}
|
||||
|
||||
if (len < 0)
|
||||
if (length < 0)
|
||||
break;
|
||||
|
||||
if (len > size)
|
||||
len = size;
|
||||
if (length > size)
|
||||
length = size;
|
||||
|
||||
ret = pa_stream_write(pulse->stream, src, len, NULL, 0LL, PA_SEEK_RELATIVE);
|
||||
status = pa_stream_write(pulse->stream, pcmData, length, NULL, 0LL, PA_SEEK_RELATIVE);
|
||||
|
||||
if (ret < 0)
|
||||
if (status < 0)
|
||||
{
|
||||
DEBUG_WARN("pa_stream_write failed (%d)",
|
||||
pa_context_errno(pulse->context));
|
||||
break;
|
||||
}
|
||||
|
||||
src += len;
|
||||
size -= len;
|
||||
pcmData += length;
|
||||
size -= length;
|
||||
}
|
||||
|
||||
pa_threaded_mainloop_unlock(pulse->mainloop);
|
||||
@ -595,6 +670,10 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
|
||||
|
||||
pulse->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
#ifdef WITH_GSM
|
||||
pulse->gsmBuffer = Stream_New(NULL, 4096);
|
||||
#endif
|
||||
|
||||
pulse->mainloop = pa_threaded_mainloop_new();
|
||||
|
||||
if (!pulse->mainloop)
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/thread.h>
|
||||
@ -62,9 +63,11 @@ struct rdpsnd_plugin
|
||||
UINT32 OpenHandle;
|
||||
wMessagePipe* MsgPipe;
|
||||
|
||||
wLog* log;
|
||||
HANDLE ScheduleThread;
|
||||
|
||||
BYTE cBlockNo;
|
||||
UINT16 wQualityMode;
|
||||
int wCurrentFormatNo;
|
||||
|
||||
AUDIO_FORMAT* ServerFormats;
|
||||
@ -91,7 +94,7 @@ struct rdpsnd_plugin
|
||||
rdpsndDevicePlugin* device;
|
||||
};
|
||||
|
||||
static void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE cConfirmedBlockNo);
|
||||
static void rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave);
|
||||
|
||||
static void* rdpsnd_schedule_thread(void* arg)
|
||||
{
|
||||
@ -123,9 +126,10 @@ static void* rdpsnd_schedule_thread(void* arg)
|
||||
Sleep(wTimeDiff);
|
||||
}
|
||||
|
||||
rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo);
|
||||
free(wave);
|
||||
rdpsnd_confirm_wave(rdpsnd, wave);
|
||||
|
||||
message.wParam = NULL;
|
||||
free(wave);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -139,9 +143,11 @@ void rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
|
||||
Stream_Write_UINT8(pdu, SNDC_QUALITYMODE); /* msgType */
|
||||
Stream_Write_UINT8(pdu, 0); /* bPad */
|
||||
Stream_Write_UINT16(pdu, 4); /* BodySize */
|
||||
Stream_Write_UINT16(pdu, HIGH_QUALITY); /* wQualityMode */
|
||||
Stream_Write_UINT16(pdu, rdpsnd->wQualityMode); /* wQualityMode */
|
||||
Stream_Write_UINT16(pdu, 0); /* Reserved */
|
||||
|
||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "QualityMode: %d", rdpsnd->wQualityMode);
|
||||
|
||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||
}
|
||||
|
||||
@ -258,6 +264,8 @@ void rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
|
||||
Stream_Write(pdu, clientFormat->data, clientFormat->cbSize);
|
||||
}
|
||||
|
||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Client Audio Formats");
|
||||
|
||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||
}
|
||||
|
||||
@ -310,6 +318,8 @@ void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
|
||||
rdpsnd_select_supported_audio_formats(rdpsnd);
|
||||
|
||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Server Audio Formats");
|
||||
|
||||
rdpsnd_send_client_audio_formats(rdpsnd);
|
||||
|
||||
if (wVersion >= 6)
|
||||
@ -330,6 +340,9 @@ void rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, U
|
||||
Stream_Write_UINT16(pdu, wTimeStamp);
|
||||
Stream_Write_UINT16(pdu, wPackSize);
|
||||
|
||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Training Response: wTimeStamp: %d wPackSize: %d",
|
||||
wTimeStamp, wPackSize);
|
||||
|
||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||
}
|
||||
|
||||
@ -341,6 +354,9 @@ static void rdpsnd_recv_training_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
Stream_Read_UINT16(s, wTimeStamp);
|
||||
Stream_Read_UINT16(s, wPackSize);
|
||||
|
||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Training Request: wTimeStamp: %d wPackSize: %d",
|
||||
wTimeStamp, wPackSize);
|
||||
|
||||
rdpsnd_send_training_confirm_pdu(rdpsnd, wTimeStamp, wPackSize);
|
||||
}
|
||||
|
||||
@ -361,6 +377,9 @@ static void rdpsnd_recv_wave_info_pdu(rdpsndPlugin* rdpsnd, wStream* s, UINT16 B
|
||||
|
||||
format = &rdpsnd->ClientFormats[wFormatNo];
|
||||
|
||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "WaveInfo: cBlockNo: %d wFormatNo: %d",
|
||||
rdpsnd->cBlockNo, wFormatNo);
|
||||
|
||||
if (!rdpsnd->isOpen)
|
||||
{
|
||||
rdpsnd->isOpen = TRUE;
|
||||
@ -399,6 +418,14 @@ void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE
|
||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||
}
|
||||
|
||||
void rdpsnd_confirm_wave(rdpsndPlugin* rdpsnd, RDPSND_WAVE* wave)
|
||||
{
|
||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "WaveConfirm: cBlockNo: %d wTimeStamp: %d wTimeDiff: %d",
|
||||
wave->cBlockNo, wave->wTimeStampB, wave->wTimeStampB - wave->wTimeStampA);
|
||||
|
||||
rdpsnd_send_wave_confirm_pdu(rdpsnd, wave->wTimeStampB, wave->cBlockNo);
|
||||
}
|
||||
|
||||
static void rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
|
||||
{
|
||||
MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave, NULL);
|
||||
@ -438,6 +465,9 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
format = &rdpsnd->ClientFormats[rdpsnd->wCurrentFormatNo];
|
||||
wave->wAudioLength = rdpsnd_compute_audio_time_length(format, size);
|
||||
|
||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Wave: cBlockNo: %d wTimeStamp: %d",
|
||||
wave->cBlockNo, wave->wTimeStampA);
|
||||
|
||||
if (!rdpsnd->device)
|
||||
{
|
||||
free(wave);
|
||||
@ -468,6 +498,8 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
|
||||
static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd)
|
||||
{
|
||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Close");
|
||||
|
||||
if (rdpsnd->device)
|
||||
{
|
||||
IFCALL(rdpsnd->device->Close, rdpsnd->device);
|
||||
@ -482,6 +514,8 @@ static void rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
|
||||
Stream_Read_UINT32(s, dwVolume);
|
||||
|
||||
WLog_Print(rdpsnd->log, WLOG_DEBUG, "Volume: 0x%04X", dwVolume);
|
||||
|
||||
if (rdpsnd->device)
|
||||
{
|
||||
IFCALL(rdpsnd->device->SetVolume, rdpsnd->device, dwVolume);
|
||||
@ -597,6 +631,7 @@ COMMAND_LINE_ARGUMENT_A rdpsnd_args[] =
|
||||
{ "rate", COMMAND_LINE_VALUE_REQUIRED, "<rate>", NULL, NULL, -1, NULL, "rate" },
|
||||
{ "channel", COMMAND_LINE_VALUE_REQUIRED, "<channel>", NULL, NULL, -1, NULL, "channel" },
|
||||
{ "latency", COMMAND_LINE_VALUE_REQUIRED, "<latency>", NULL, NULL, -1, NULL, "latency" },
|
||||
{ "quality", COMMAND_LINE_VALUE_REQUIRED, "<quality mode>", NULL, NULL, -1, NULL, "quality mode" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
@ -606,10 +641,13 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
|
||||
rdpsnd->wQualityMode = HIGH_QUALITY; /* default quality mode */
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
rdpsnd_args, flags, rdpsnd, NULL, NULL);
|
||||
|
||||
if (status < 0)
|
||||
return;
|
||||
|
||||
@ -646,6 +684,24 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
|
||||
{
|
||||
rdpsnd->latency = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "quality")
|
||||
{
|
||||
int wQualityMode = DYNAMIC_QUALITY;
|
||||
|
||||
if (_stricmp(arg->Value, "dynamic") == 0)
|
||||
wQualityMode = DYNAMIC_QUALITY;
|
||||
else if (_stricmp(arg->Value, "medium") == 0)
|
||||
wQualityMode = MEDIUM_QUALITY;
|
||||
else if (_stricmp(arg->Value, "high") == 0)
|
||||
wQualityMode = HIGH_QUALITY;
|
||||
else
|
||||
wQualityMode = atoi(arg->Value);
|
||||
|
||||
if ((wQualityMode < 0) || (wQualityMode > 2))
|
||||
wQualityMode = DYNAMIC_QUALITY;
|
||||
|
||||
rdpsnd->wQualityMode = (UINT16) wQualityMode;
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
|
||||
@ -1018,6 +1074,9 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
|
||||
CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, pEntryPoints->cbSize);
|
||||
|
||||
rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client");
|
||||
//WLog_SetLogLevel(rdpsnd->log, WLOG_TRACE);
|
||||
|
||||
rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle,
|
||||
&rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpsnd_virtual_channel_init_event);
|
||||
|
||||
|
@ -43,12 +43,22 @@
|
||||
#define AVMEDIA_TYPE_AUDIO 1
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 54
|
||||
#define MAX_AUDIO_FRAME_SIZE AVCODEC_MAX_AUDIO_FRAME_SIZE
|
||||
#else
|
||||
#define MAX_AUDIO_FRAME_SIZE 192000
|
||||
#endif
|
||||
|
||||
typedef struct _TSMFFFmpegDecoder
|
||||
{
|
||||
ITSMFDecoder iface;
|
||||
|
||||
int media_type;
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 55
|
||||
enum CodecID codec_id;
|
||||
#else
|
||||
enum AVCodecID codec_id;
|
||||
#endif
|
||||
AVCodecContext* codec_context;
|
||||
AVCodec* codec;
|
||||
AVFrame* frame;
|
||||
@ -98,6 +108,7 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MED
|
||||
mdecoder->codec_context->channels = media_type->Channels;
|
||||
mdecoder->codec_context->block_align = media_type->BlockAlign;
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 55
|
||||
#ifdef AV_CPU_FLAG_SSE2
|
||||
mdecoder->codec_context->dsp_mask = AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMX2;
|
||||
#else
|
||||
@ -107,6 +118,13 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MED
|
||||
mdecoder->codec_context->dsp_mask = FF_MM_SSE2 | FF_MM_MMX2;
|
||||
#endif
|
||||
#endif
|
||||
#else /* LIBAVCODEC_VERSION_MAJOR < 55 */
|
||||
#ifdef AV_CPU_FLAG_SSE2
|
||||
av_set_cpu_flags_mask(AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMX2);
|
||||
#else
|
||||
av_set_cpu_flags_mask(FF_MM_SSE2 | FF_MM_MMX2);
|
||||
#endif
|
||||
#endif /* LIBAVCODEC_VERSION_MAJOR < 55 */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -351,7 +369,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
|
||||
#endif
|
||||
|
||||
if (mdecoder->decoded_size_max == 0)
|
||||
mdecoder->decoded_size_max = AVCODEC_MAX_AUDIO_FRAME_SIZE + 16;
|
||||
mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16;
|
||||
mdecoder->decoded_data = malloc(mdecoder->decoded_size_max);
|
||||
ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size_max);
|
||||
/* align the memory for SSE2 needs */
|
||||
@ -363,7 +381,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
|
||||
while (src_size > 0)
|
||||
{
|
||||
/* Ensure enough space for decoding */
|
||||
if (mdecoder->decoded_size_max - mdecoder->decoded_size < AVCODEC_MAX_AUDIO_FRAME_SIZE)
|
||||
if (mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE)
|
||||
{
|
||||
mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16;
|
||||
mdecoder->decoded_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max);
|
||||
|
@ -19,11 +19,10 @@ if (NOT ANDROID_NDK)
|
||||
message(FATAL_ERROR "ANDROID_NDK not set but required for building android native library.")
|
||||
endif()
|
||||
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, BOTH)
|
||||
find_program(NDK_COMMAND ndk-build)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, ONLY)
|
||||
set(CMAKE_PROGRAM_PATH ${ANDROID_NDK})
|
||||
find_program(NDK_COMMAND ndk-build CMAKE_FIND_ROOT_PATH_BOTH)
|
||||
|
||||
if(NDK_COMMAND STREQUAL "ANT_COMMAND-NOTFOUND")
|
||||
if(NDK_COMMAND STREQUAL "NDK_COMMAND-NOTFOUND")
|
||||
message(FATAL_ERROR "ndk-build not found but required to build native lib")
|
||||
endif()
|
||||
|
||||
@ -34,9 +33,9 @@ if(ANDROID_BUILD_JAVA)
|
||||
endif()
|
||||
# And isn't shiped with the android ndk/sdk so
|
||||
# we need to find it on the local machine
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, BOTH)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
|
||||
find_program(ANT_COMMAND ant)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, ONLY)
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
|
||||
|
||||
if(ANT_COMMAND STREQUAL "ANT_COMMAND-NOTFOUND")
|
||||
message(FATAL_ERROR "ant not found but required to build android java")
|
||||
|
@ -15,6 +15,6 @@
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
build.dir=@CMAKE_CURRENT_BINARY_DIR@
|
||||
source.dir=@CMAKE_CURRENT_SOURCE_DIR@/src
|
||||
source.path=@CMAKE_CURRENT_SOURCE_DIR@/src:@CMAKE_CURRENT_BINARY_DIR@/src
|
||||
out.dir=@CMAKE_CURRENT_BINARY_DIR@/bin
|
||||
|
||||
|
@ -26,6 +26,14 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build.xml.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/build.xml @ONLY)
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/project.properties.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/project.properties @ONLY)
|
||||
|
||||
# The following is required if building android out of tree
|
||||
if (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set (AFREERDP_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||
else()
|
||||
set (AFREERDP_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src:${CMAKE_CURRENT_SOURCE_DIR}/../FreeRDPCore/src")
|
||||
endif()
|
||||
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ant.properties.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ant.properties @ONLY)
|
||||
|
||||
|
@ -15,6 +15,5 @@
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
build.dir=@CMAKE_CURRENT_BINARY_DIR@
|
||||
source.dir=@CMAKE_CURRENT_SOURCE_DIR@/src
|
||||
source.dir=@AFREERDP_SOURCE_DIR@
|
||||
out.dir=@CMAKE_CURRENT_BINARY_DIR@/bin
|
||||
|
||||
|
@ -1051,6 +1051,10 @@ void mac_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap)
|
||||
void mac_begin_paint(rdpContext* context)
|
||||
{
|
||||
rdpGdi* gdi = context->gdi;
|
||||
|
||||
if (!gdi)
|
||||
return;
|
||||
|
||||
gdi->primary->hdc->hwnd->invalid->null = 1;
|
||||
}
|
||||
|
||||
@ -1063,11 +1067,15 @@ void mac_end_paint(rdpContext* context)
|
||||
int i;
|
||||
rdpGdi* gdi;
|
||||
NSRect drawRect;
|
||||
int ww, wh, dw, dh;
|
||||
mfContext* mfc = (mfContext*) context;
|
||||
MRDPView* view = (MRDPView*) mfc->view;
|
||||
|
||||
int ww, wh, dw, dh;
|
||||
|
||||
gdi = context->gdi;
|
||||
|
||||
if (!gdi)
|
||||
return;
|
||||
|
||||
ww = mfc->client_width;
|
||||
wh = mfc->client_height;
|
||||
dw = mfc->context.settings->DesktopWidth;
|
||||
@ -1081,8 +1089,6 @@ void mac_end_paint(rdpContext* context)
|
||||
|
||||
if (context->gdi->drawing != context->gdi->primary)
|
||||
return;
|
||||
|
||||
gdi = context->gdi;
|
||||
|
||||
for (i = 0; i < gdi->primary->hdc->hwnd->ninvalid; i++)
|
||||
{
|
||||
|
@ -51,10 +51,13 @@ static UINT32 get_local_format_id_by_name(cliprdrContext *cliprdr, void *format_
|
||||
formatMapping *map;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cliprdr->map_size; i++) {
|
||||
for (i = 0; i < cliprdr->map_size; i++)
|
||||
{
|
||||
map = &cliprdr->format_mappings[i];
|
||||
if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) {
|
||||
if (map->name) {
|
||||
if ((cliprdr->capabilities & CB_USE_LONG_FORMAT_NAMES) != 0)
|
||||
{
|
||||
if (map->name)
|
||||
{
|
||||
if (memcmp(map->name, format_name, wcslen((LPCWSTR)format_name)) == 0)
|
||||
return map->local_format_id;
|
||||
}
|
||||
@ -69,9 +72,11 @@ static UINT32 get_remote_format_id(cliprdrContext *cliprdr, UINT32 local_format)
|
||||
formatMapping *map;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cliprdr->map_size; i++) {
|
||||
for (i = 0; i < cliprdr->map_size; i++)
|
||||
{
|
||||
map = &cliprdr->format_mappings[i];
|
||||
if (map->local_format_id == local_format) {
|
||||
if (map->local_format_id == local_format)
|
||||
{
|
||||
return map->remote_format_id;
|
||||
}
|
||||
}
|
||||
@ -81,9 +86,10 @@ static UINT32 get_remote_format_id(cliprdrContext *cliprdr, UINT32 local_format)
|
||||
|
||||
static void map_ensure_capacity(cliprdrContext *cliprdr)
|
||||
{
|
||||
if (cliprdr->map_size >= cliprdr->map_capacity) {
|
||||
if (cliprdr->map_size >= cliprdr->map_capacity)
|
||||
{
|
||||
cliprdr->format_mappings = (formatMapping *)realloc(cliprdr->format_mappings,
|
||||
cliprdr->map_capacity * 2);
|
||||
sizeof(formatMapping) * cliprdr->map_capacity * 2);
|
||||
cliprdr->map_capacity *= 2;
|
||||
}
|
||||
}
|
||||
@ -93,13 +99,16 @@ static void clear_format_map(cliprdrContext *cliprdr)
|
||||
formatMapping *map;
|
||||
int i;
|
||||
|
||||
if (cliprdr->format_mappings) {
|
||||
for (i = 0; i < cliprdr->map_size; i++) {
|
||||
if (cliprdr->format_mappings)
|
||||
{
|
||||
for (i = 0; i < cliprdr->map_capacity; i++)
|
||||
{
|
||||
map = &cliprdr->format_mappings[i];
|
||||
map->remote_format_id = 0;
|
||||
map->local_format_id = 0;
|
||||
|
||||
if (map->name) {
|
||||
if (map->name)
|
||||
{
|
||||
free(map->name);
|
||||
map->name = NULL;
|
||||
}
|
||||
@ -119,7 +128,8 @@ static void cliprdr_send_format_list(cliprdrContext *cliprdr)
|
||||
int len = 0;
|
||||
int namelen;
|
||||
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard)) {
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard))
|
||||
{
|
||||
DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
|
||||
return;
|
||||
}
|
||||
@ -130,23 +140,36 @@ static void cliprdr_send_format_list(cliprdrContext *cliprdr)
|
||||
format_data = (BYTE *)calloc(1, data_size);
|
||||
assert(format_data != NULL);
|
||||
|
||||
while (format = EnumClipboardFormats(format)) {
|
||||
while (format = EnumClipboardFormats(format))
|
||||
{
|
||||
Write_UINT32(format_data + len, format);
|
||||
len += 4;
|
||||
if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) {
|
||||
if (format >= CF_MAX) {
|
||||
if ((cliprdr->capabilities & CB_USE_LONG_FORMAT_NAMES) != 0)
|
||||
{
|
||||
if (format >= CF_MAX)
|
||||
{
|
||||
namelen = GetClipboardFormatNameW(format, (LPWSTR)(format_data + len), MAX_PATH);
|
||||
len += namelen * sizeof(WCHAR);
|
||||
}
|
||||
len += 2; /* end of Unicode string */
|
||||
} else {
|
||||
ZeroMemory(format_data + len, 32);
|
||||
if (format >= CF_MAX) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (format >= CF_MAX)
|
||||
{
|
||||
static wchar_t wName[MAX_PATH] = {0};
|
||||
int wLen;
|
||||
|
||||
ZeroMemory(wName, MAX_PATH*2);
|
||||
GetClipboardFormatNameW(format, wName, MAX_PATH);
|
||||
memcpy(format_data + len, wName, 32); /* truncate the long name to 32 bytes */
|
||||
wLen = GetClipboardFormatNameW(format, wName, MAX_PATH);
|
||||
if (wLen < 16)
|
||||
{
|
||||
memcpy(format_data + len, wName, wLen * sizeof(WCHAR));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(format_data + len, wName, 32); /* truncate the long name to 32 bytes */
|
||||
}
|
||||
}
|
||||
len += 32;
|
||||
}
|
||||
@ -180,6 +203,8 @@ int cliprdr_send_data_request(cliprdrContext *cliprdr, UINT32 format)
|
||||
return -1;
|
||||
|
||||
cliprdr_event->format = get_remote_format_id(cliprdr, format);
|
||||
if (cliprdr_event->format == 0)
|
||||
return -1;
|
||||
|
||||
ret = freerdp_channels_send_event(cliprdr->channels, (wMessage *)cliprdr_event);
|
||||
|
||||
@ -196,12 +221,14 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
|
||||
{
|
||||
static cliprdrContext *cliprdr = NULL;
|
||||
|
||||
switch (Msg) {
|
||||
switch (Msg)
|
||||
{
|
||||
case WM_CREATE:
|
||||
cliprdr = (cliprdrContext *)((CREATESTRUCT *)lParam)->lpCreateParams;
|
||||
cliprdr->hwndNextViewer = SetClipboardViewer(hWnd);
|
||||
|
||||
if (cliprdr->hwndNextViewer == NULL && GetLastError() != 0) {
|
||||
if (cliprdr->hwndNextViewer == NULL && GetLastError() != 0)
|
||||
{
|
||||
DEBUG_CLIPRDR("error: SetClipboardViewer failed with 0x%0x.", GetLastError());
|
||||
}
|
||||
cliprdr->hwndClipboard = hWnd;
|
||||
@ -212,17 +239,23 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
|
||||
break;
|
||||
|
||||
case WM_CHANGECBCHAIN:
|
||||
if (cliprdr->hwndNextViewer == (HWND)wParam) {
|
||||
if (cliprdr->hwndNextViewer == (HWND)wParam)
|
||||
{
|
||||
cliprdr->hwndNextViewer = (HWND)lParam;
|
||||
} else if (cliprdr->hwndNextViewer != NULL) {
|
||||
}
|
||||
else if (cliprdr->hwndNextViewer != NULL)
|
||||
{
|
||||
SendMessage(cliprdr->hwndNextViewer, Msg, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_DRAWCLIPBOARD:
|
||||
if (cliprdr->channel_initialized) {
|
||||
if (GetClipboardOwner() != cliprdr->hwndClipboard) {
|
||||
if (!cliprdr->hmem) {
|
||||
if (cliprdr->channel_initialized)
|
||||
{
|
||||
if (GetClipboardOwner() != cliprdr->hwndClipboard)
|
||||
{
|
||||
if (!cliprdr->hmem)
|
||||
{
|
||||
cliprdr->hmem = GlobalFree(cliprdr->hmem);
|
||||
}
|
||||
cliprdr_send_format_list(cliprdr);
|
||||
@ -234,7 +267,8 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
|
||||
|
||||
case WM_RENDERALLFORMATS:
|
||||
/* discard all contexts in clipboard */
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard)) {
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard))
|
||||
{
|
||||
DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
|
||||
break;
|
||||
}
|
||||
@ -243,12 +277,14 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
|
||||
break;
|
||||
|
||||
case WM_RENDERFORMAT:
|
||||
if (cliprdr_send_data_request(cliprdr, (UINT32)wParam) != 0) {
|
||||
if (cliprdr_send_data_request(cliprdr, (UINT32)wParam) != 0)
|
||||
{
|
||||
DEBUG_CLIPRDR("error: cliprdr_send_data_request failed.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (SetClipboardData(wParam, cliprdr->hmem) == NULL) {
|
||||
if (SetClipboardData(wParam, cliprdr->hmem) == NULL)
|
||||
{
|
||||
DEBUG_CLIPRDR("SetClipboardData failed with 0x%x", GetLastError());
|
||||
cliprdr->hmem = GlobalFree(cliprdr->hmem);
|
||||
}
|
||||
@ -292,7 +328,8 @@ static int create_cliprdr_window(cliprdrContext *cliprdr)
|
||||
L"rdpclip",
|
||||
0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), cliprdr);
|
||||
|
||||
if (cliprdr->hwndClipboard == NULL) {
|
||||
if (cliprdr->hwndClipboard == NULL)
|
||||
{
|
||||
DEBUG_CLIPRDR("error: CreateWindowEx failed with %x.", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
@ -308,16 +345,21 @@ static void *cliprdr_thread_func(void *arg)
|
||||
int ret;
|
||||
HRESULT result;
|
||||
|
||||
if ((ret = create_cliprdr_window(cliprdr)) != 0) {
|
||||
if ((ret = create_cliprdr_window(cliprdr)) != 0)
|
||||
{
|
||||
DEBUG_CLIPRDR("error: create clipboard window failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((mcode = GetMessage(&msg, 0, 0, 0) != 0)) {
|
||||
if (mcode == -1) {
|
||||
while ((mcode = GetMessage(&msg, 0, 0, 0) != 0))
|
||||
{
|
||||
if (mcode == -1)
|
||||
{
|
||||
DEBUG_CLIPRDR("error: clipboard thread GetMessage failed.");
|
||||
break;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
@ -362,7 +404,8 @@ void wf_cliprdr_uninit(wfContext* wfc)
|
||||
if (cliprdr->hwndClipboard)
|
||||
PostMessage(cliprdr->hwndClipboard, WM_QUIT, 0, 0);
|
||||
|
||||
if (cliprdr->cliprdr_thread) {
|
||||
if (cliprdr->cliprdr_thread)
|
||||
{
|
||||
WaitForSingleObject(cliprdr->cliprdr_thread, INFINITE);
|
||||
CloseHandle(cliprdr->cliprdr_thread);
|
||||
}
|
||||
@ -406,23 +449,32 @@ static void wf_cliprdr_process_cb_data_request_event(wfContext *wfc, RDP_CB_DATA
|
||||
|
||||
local_format = event->format;
|
||||
|
||||
if (local_format == 0x9) { /* FORMAT_ID_PALETTE */
|
||||
if (local_format == 0x9) /* FORMAT_ID_PALETTE */
|
||||
{
|
||||
/* TODO: implement this */
|
||||
DEBUG_CLIPRDR("FORMAT_ID_PALETTE is not supported yet.");
|
||||
} else if (local_format == 0x3) { /* FORMAT_ID_MATEFILE */
|
||||
}
|
||||
else if (local_format == 0x3) /* FORMAT_ID_MATEFILE */
|
||||
{
|
||||
/* TODO: implement this */
|
||||
DEBUG_CLIPRDR("FORMAT_ID_MATEFILE is not supported yet.");
|
||||
} else if (local_format == RegisterClipboardFormatW(L"FileGroupDescriptorW")) {
|
||||
}
|
||||
else if (local_format == RegisterClipboardFormatW(L"FileGroupDescriptorW"))
|
||||
{
|
||||
/* TODO: implement this */
|
||||
DEBUG_CLIPRDR("FileGroupDescriptorW is not supported yet.");
|
||||
} else {
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard)) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard))
|
||||
{
|
||||
DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
hClipdata = GetClipboardData(event->format);
|
||||
if (!hClipdata) {
|
||||
if (!hClipdata)
|
||||
{
|
||||
DEBUG_CLIPRDR("GetClipboardData failed.");
|
||||
CloseClipboard();
|
||||
return;
|
||||
@ -466,8 +518,10 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA
|
||||
|
||||
clear_format_map(cliprdr);
|
||||
|
||||
if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) {
|
||||
while (left_size >= 6) {
|
||||
if ((cliprdr->capabilities & CB_USE_LONG_FORMAT_NAMES) != 0)
|
||||
{
|
||||
while (left_size >= 6)
|
||||
{
|
||||
formatMapping *map;
|
||||
BYTE* tmp;
|
||||
int name_len;
|
||||
@ -475,19 +529,24 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA
|
||||
map = &cliprdr->format_mappings[i++];
|
||||
|
||||
Read_UINT32(p, map->remote_format_id);
|
||||
map->name = NULL;
|
||||
|
||||
/* get name_len */
|
||||
for (tmp = p, name_len = 0; tmp + 1 < end_mark; tmp += 2, name_len += 2) {
|
||||
for (tmp = p, name_len = 0; tmp + 1 < end_mark; tmp += 2, name_len += 2)
|
||||
{
|
||||
if (*((unsigned short*) tmp) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (name_len > 0) {
|
||||
if (name_len > 0)
|
||||
{
|
||||
map->name = malloc(name_len + 2);
|
||||
memcpy(map->name, p, name_len + 2);
|
||||
|
||||
map->local_format_id = RegisterClipboardFormatW((LPCWSTR)map->name);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
map->local_format_id = map->remote_format_id;
|
||||
}
|
||||
|
||||
@ -498,43 +557,58 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA
|
||||
|
||||
map_ensure_capacity(cliprdr);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = 0; k < event->raw_format_data_size / 36; k++) {
|
||||
for (k = 0; k < event->raw_format_data_size / 36; k++)
|
||||
{
|
||||
formatMapping *map;
|
||||
int name_len;
|
||||
|
||||
map = &cliprdr->format_mappings[i++];
|
||||
|
||||
Read_UINT32(p, map->remote_format_id);
|
||||
map->name = NULL;
|
||||
|
||||
if (event->raw_format_unicode) {
|
||||
if (event->raw_format_unicode)
|
||||
{
|
||||
/* get name_len, in bytes, if the file name is truncated, no terminated null will be included. */
|
||||
for (name_len = 0; name_len < 32; name_len += 2) {
|
||||
for (name_len = 0; name_len < 32; name_len += 2)
|
||||
{
|
||||
if (*((unsigned short*) (p + name_len)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (name_len > 0) {
|
||||
if (name_len > 0)
|
||||
{
|
||||
map->name = calloc(1, name_len + 2);
|
||||
memcpy(map->name, p, name_len);
|
||||
map->local_format_id = RegisterClipboardFormatW((LPCWSTR)map->name);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
map->local_format_id = map->remote_format_id;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/* get name_len, in bytes, if the file name is truncated, no terminated null will be included. */
|
||||
for (name_len = 0; name_len < 32; name_len += 1) {
|
||||
for (name_len = 0; name_len < 32; name_len += 1)
|
||||
{
|
||||
if (*((unsigned char*) (p + name_len)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (name_len > 0) {
|
||||
if (name_len > 0)
|
||||
{
|
||||
map->name = calloc(1, name_len + 1);
|
||||
memcpy(map->name, p, name_len);
|
||||
map->local_format_id = RegisterClipboardFormatA((LPCSTR)map->name);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
map->local_format_id = map->remote_format_id;
|
||||
}
|
||||
}
|
||||
@ -545,18 +619,21 @@ static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMA
|
||||
}
|
||||
}
|
||||
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard)) {
|
||||
if (!OpenClipboard(cliprdr->hwndClipboard))
|
||||
{
|
||||
DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EmptyClipboard()) {
|
||||
if (!EmptyClipboard())
|
||||
{
|
||||
DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError());
|
||||
CloseClipboard();
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < cliprdr->map_size; i++) {
|
||||
for (i = 0; i < cliprdr->map_size; i++)
|
||||
{
|
||||
SetClipboardData(cliprdr->format_mappings[i].local_format_id, NULL);
|
||||
}
|
||||
|
||||
@ -580,7 +657,8 @@ static void wf_cliprdr_process_cb_data_response_event(wfContext *wfc, RDP_CB_DAT
|
||||
|
||||
void wf_process_cliprdr_event(wfContext *wfc, wMessage *event)
|
||||
{
|
||||
switch (GetMessageType(event->id)) {
|
||||
switch (GetMessageType(event->id))
|
||||
{
|
||||
case CliprdrChannel_ClipCaps:
|
||||
wf_cliprdr_process_cb_clip_caps_event(wfc, (RDP_CB_CLIP_CAPS *)event);
|
||||
break;
|
||||
|
@ -466,7 +466,6 @@ void wf_gdi_multi_opaque_rect(wfContext* wfc, MULTI_OPAQUE_RECT_ORDER* multi_opa
|
||||
rect.bottom = rectangle->top + rectangle->height;
|
||||
brush = CreateSolidBrush(brush_color);
|
||||
|
||||
brush = CreateSolidBrush(brush_color);
|
||||
FillRect(wfc->drawing->hdc, &rect, brush);
|
||||
|
||||
if (wfc->drawing == wfc->primary)
|
||||
|
@ -226,43 +226,43 @@ BOOL freerdp_client_rdp_file_set_string(rdpFile* file, char* name, char* value)
|
||||
#endif
|
||||
|
||||
if (_stricmp(name, "username") == 0)
|
||||
file->Username = value;
|
||||
file->Username = _strdup(value);
|
||||
else if (_stricmp(name, "domain") == 0)
|
||||
file->Domain = value;
|
||||
file->Domain = _strdup(value);
|
||||
else if (_stricmp(name, "full address") == 0)
|
||||
file->FullAddress = value;
|
||||
file->FullAddress = _strdup(value);
|
||||
else if (_stricmp(name, "alternate full address") == 0)
|
||||
file->AlternateFullAddress = value;
|
||||
file->AlternateFullAddress = _strdup(value);
|
||||
else if (_stricmp(name, "usbdevicestoredirect") == 0)
|
||||
file->UsbDevicesToRedirect = value;
|
||||
file->UsbDevicesToRedirect = _strdup(value);
|
||||
else if (_stricmp(name, "loadbalanceinfo") == 0)
|
||||
file->LoadBalanceInfo = value;
|
||||
file->LoadBalanceInfo = _strdup(value);
|
||||
else if (_stricmp(name, "remoteapplicationname") == 0)
|
||||
file->RemoteApplicationName = value;
|
||||
file->RemoteApplicationName = _strdup(value);
|
||||
else if (_stricmp(name, "remoteapplicationicon") == 0)
|
||||
file->RemoteApplicationIcon = value;
|
||||
file->RemoteApplicationIcon = _strdup(value);
|
||||
else if (_stricmp(name, "remoteapplicationprogram") == 0)
|
||||
file->RemoteApplicationProgram = value;
|
||||
file->RemoteApplicationProgram = _strdup(value);
|
||||
else if (_stricmp(name, "remoteapplicationfile") == 0)
|
||||
file->RemoteApplicationFile = value;
|
||||
file->RemoteApplicationFile = _strdup(value);
|
||||
else if (_stricmp(name, "remoteapplicationguid") == 0)
|
||||
file->RemoteApplicationGuid = value;
|
||||
file->RemoteApplicationGuid = _strdup(value);
|
||||
else if (_stricmp(name, "remoteapplicationcmdline") == 0)
|
||||
file->RemoteApplicationCmdLine = value;
|
||||
file->RemoteApplicationCmdLine = _strdup(value);
|
||||
else if (_stricmp(name, "alternate shell") == 0)
|
||||
file->AlternateShell = value;
|
||||
file->AlternateShell = _strdup(value);
|
||||
else if (_stricmp(name, "shell working directory") == 0)
|
||||
file->ShellWorkingDirectory = value;
|
||||
file->ShellWorkingDirectory = _strdup(value);
|
||||
else if (_stricmp(name, "gatewayhostname") == 0)
|
||||
file->GatewayHostname = value;
|
||||
file->GatewayHostname = _strdup(value);
|
||||
else if (_stricmp(name, "kdcproxyname") == 0)
|
||||
file->KdcProxyName = value;
|
||||
file->KdcProxyName = _strdup(value);
|
||||
else if (_stricmp(name, "drivestoredirect") == 0)
|
||||
file->DrivesToRedirect = value;
|
||||
file->DrivesToRedirect = _strdup(value);
|
||||
else if (_stricmp(name, "devicestoredirect") == 0)
|
||||
file->DevicesToRedirect = value;
|
||||
file->DevicesToRedirect = _strdup(value);
|
||||
else if (_stricmp(name, "winposstr") == 0)
|
||||
file->WinPosStr = value;
|
||||
file->WinPosStr = _strdup(value);
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
@ -297,10 +297,10 @@ void freerdp_client_parse_rdp_file_string_unicode(rdpFile* file, WCHAR* name, WC
|
||||
WideCharToMultiByte(CP_UTF8, 0, value, length, valueA, length, NULL, NULL);
|
||||
valueA[length] = '\0';
|
||||
|
||||
if (!freerdp_client_rdp_file_set_string(file, nameA, valueA))
|
||||
free(valueA);
|
||||
freerdp_client_rdp_file_set_string(file, nameA, valueA);
|
||||
|
||||
free(nameA);
|
||||
free(valueA);
|
||||
}
|
||||
|
||||
void freerdp_client_parse_rdp_file_string_ascii(rdpFile* file, char* name, char* value)
|
||||
|
@ -326,7 +326,7 @@ endif()
|
||||
# rpath makes low sence for Android
|
||||
set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." )
|
||||
|
||||
set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
|
||||
set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
|
||||
if(NOT DEFINED ANDROID_NDK_SEARCH_PATHS)
|
||||
if( CMAKE_HOST_WIN32 )
|
||||
file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS )
|
||||
@ -690,6 +690,7 @@ if( BUILD_WITH_ANDROID_NDK )
|
||||
endif()
|
||||
__LIST_FILTER( __availableToolchainsLst "^[.]" )
|
||||
__LIST_FILTER( __availableToolchainsLst "llvm" )
|
||||
__LIST_FILTER( __availableToolchainsLst "renderscript" )
|
||||
__GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
|
||||
if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
|
||||
__GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
|
||||
@ -721,7 +722,7 @@ __INIT_VARIABLE( ANDROID_ABI OBSOLETE_ARM_TARGET OBSOLETE_ARM_TARGETS VALUES ${A
|
||||
# verify that target ABI is supported
|
||||
list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx )
|
||||
if( __androidAbiIdx EQUAL -1 )
|
||||
string( REPLACE ";" "\", \"", PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" )
|
||||
string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" )
|
||||
message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain.
|
||||
Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\"
|
||||
" )
|
||||
|
13
cmake/FindGSM.cmake
Normal file
13
cmake/FindGSM.cmake
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
find_path(GSM_INCLUDE_DIR gsm/gsm.h)
|
||||
|
||||
find_library(GSM_LIBRARY gsm)
|
||||
|
||||
find_package_handle_standard_args(GSM DEFAULT_MSG GSM_INCLUDE_DIR GSM_LIBRARY)
|
||||
|
||||
if(GSM_FOUND)
|
||||
set(GSM_LIBRARIES ${GSM_LIBRARY})
|
||||
set(GSM_INCLUDE_DIRS ${GSM_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(GSM_INCLUDE_DIR GSM_LIBRARY)
|
@ -44,6 +44,7 @@
|
||||
#cmakedefine WITH_PULSE
|
||||
#cmakedefine WITH_IOSAUDIO
|
||||
#cmakedefine WITH_OPENSLES
|
||||
#cmakedefine WITH_GSM
|
||||
|
||||
/* Plugins */
|
||||
#cmakedefine STATIC_CHANNELS
|
||||
|
@ -29,14 +29,15 @@ FreeRDP requires openssl libraries for building but they are not part of the
|
||||
Android NDK and therefore they need to be prebuild manually.
|
||||
Multiple source versions and builds of static openssl libraries are floating around.
|
||||
At the time of writing we have tested and used:
|
||||
https://github.com/bmiklautz/Android-external-openssl-ndk-static.
|
||||
https://github.com/bmiklautz/Android-external-openssl-ndk-static
|
||||
https://github.com/akallabeth/openssl-android
|
||||
However, any other static build should work as well.
|
||||
|
||||
To build openssl:
|
||||
|
||||
git clone git@github.com:bmiklautz/android-external-openssl-ndk-static.git
|
||||
cd android-external-openssl-ndk-static
|
||||
ndk-build # found in the Android NDK
|
||||
Set up ANDROID_NDK and ANDROID_SDK to the absolute paths on your machine.
|
||||
From the project root folder run './scripts/android_setup_build_env.sh'
|
||||
This will set up openssl and gprof helper libraries as required for FreeRDP.
|
||||
|
||||
|
||||
Building
|
||||
|
177
include/freerdp/channels/cliprdr.h
Normal file
177
include/freerdp/channels/cliprdr.h
Normal file
@ -0,0 +1,177 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Clipboard Virtual Channel Extension
|
||||
*
|
||||
* Copyright 2013 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_CLIPRDR_H
|
||||
#define FREERDP_CHANNEL_CLIPRDR_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#define CLIPRDR_SVC_CHANNEL_NAME "cliprdr"
|
||||
|
||||
/**
|
||||
* Clipboard Formats
|
||||
*/
|
||||
|
||||
#define CLIPRDR_FORMAT_RAW 0
|
||||
#define CLIPRDR_FORMAT_TEXT 1 /* "Plain Text" */
|
||||
#define CLIPRDR_FORMAT_BITMAP 2 /* "Bitmap" */
|
||||
#define CLIPRDR_FORMAT_METAFILEPICT 3 /* "Windows Metafile" */
|
||||
#define CLIPRDR_FORMAT_SYLK 4
|
||||
#define CLIPRDR_FORMAT_DIF 5
|
||||
#define CLIPRDR_FORMAT_TIFF 6
|
||||
#define CLIPRDR_FORMAT_OEMTEXT 7 /* "OEM Text" */
|
||||
#define CLIPRDR_FORMAT_DIB 8 /* "Device Independent Bitmap (DIB)" */
|
||||
#define CLIPRDR_FORMAT_PALETTE 9
|
||||
#define CLIPRDR_FORMAT_PENDATA 10
|
||||
#define CLIPRDR_FORMAT_RIFF 11
|
||||
#define CLIPRDR_FORMAT_WAVE 12
|
||||
#define CLIPRDR_FORMAT_UNICODETEXT 13 /* "Unicode Text" */
|
||||
#define CLIPRDR_FORMAT_ENHMETAFILE 14 /* "Enhanced Metafile" */
|
||||
#define CLIPRDR_FORMAT_HDROP 15 /* "File List" */
|
||||
#define CLIPRDR_FORMAT_LOCALE 16 /* "Locale Identifier" */
|
||||
#define CLIPRDR_FORMAT_DIBV5 17
|
||||
#define CLIPRDR_FORMAT_MAX 18
|
||||
|
||||
#define CB_FORMAT_RAW 0x0000
|
||||
#define CB_FORMAT_TEXT 0x0001
|
||||
#define CB_FORMAT_DIB 0x0008
|
||||
#define CB_FORMAT_UNICODETEXT 0x000D
|
||||
#define CB_FORMAT_HTML 0xD010
|
||||
#define CB_FORMAT_PNG 0xD011
|
||||
#define CB_FORMAT_JPEG 0xD012
|
||||
#define CB_FORMAT_GIF 0xD013
|
||||
|
||||
/* CLIPRDR_HEADER.msgType */
|
||||
#define CB_MONITOR_READY 0x0001
|
||||
#define CB_FORMAT_LIST 0x0002
|
||||
#define CB_FORMAT_LIST_RESPONSE 0x0003
|
||||
#define CB_FORMAT_DATA_REQUEST 0x0004
|
||||
#define CB_FORMAT_DATA_RESPONSE 0x0005
|
||||
#define CB_TEMP_DIRECTORY 0x0006
|
||||
#define CB_CLIP_CAPS 0x0007
|
||||
#define CB_FILECONTENTS_REQUEST 0x0008
|
||||
#define CB_FILECONTENTS_RESPONSE 0x0009
|
||||
#define CB_LOCK_CLIPDATA 0x000A
|
||||
#define CB_UNLOCK_CLIPDATA 0x000B
|
||||
|
||||
/* CLIPRDR_HEADER.msgFlags */
|
||||
#define CB_RESPONSE_OK 0x0001
|
||||
#define CB_RESPONSE_FAIL 0x0002
|
||||
#define CB_ASCII_NAMES 0x0004
|
||||
|
||||
/* CLIPRDR_CAPS_SET.capabilitySetType */
|
||||
#define CB_CAPSTYPE_GENERAL 0x0001
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */
|
||||
#define CB_CAPSTYPE_GENERAL_LEN 12
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.version */
|
||||
#define CB_CAPS_VERSION_1 0x00000001
|
||||
#define CB_CAPS_VERSION_2 0x00000002
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
|
||||
#define CB_USE_LONG_FORMAT_NAMES 0x00000002
|
||||
#define CB_STREAM_FILECLIP_ENABLED 0x00000004
|
||||
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008
|
||||
#define CB_CAN_LOCK_CLIPDATA 0x00000010
|
||||
|
||||
#define DEFINE_CLIPRDR_HEADER_COMMON() \
|
||||
UINT16 msgType; \
|
||||
UINT16 msgFlags; \
|
||||
UINT32 dataLen
|
||||
|
||||
struct _CLIPRDR_HEADER
|
||||
{
|
||||
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||
};
|
||||
typedef struct _CLIPRDR_HEADER CLIPRDR_HEADER;
|
||||
|
||||
struct _CLIPRDR_CAPABILITY_SET
|
||||
{
|
||||
UINT16 capabilitySetType;
|
||||
UINT16 capabilitySetLength;
|
||||
};
|
||||
typedef struct _CLIPRDR_CAPABILITY_SET CLIPRDR_CAPABILITY_SET;
|
||||
|
||||
struct _CLIPRDR_GENERAL_CAPABILITY_SET
|
||||
{
|
||||
UINT16 capabilitySetType;
|
||||
UINT16 capabilitySetLength;
|
||||
|
||||
UINT32 version;
|
||||
UINT32 generalFlags;
|
||||
};
|
||||
typedef struct _CLIPRDR_GENERAL_CAPABILITY_SET CLIPRDR_GENERAL_CAPABILITY_SET;
|
||||
|
||||
struct _CLIPRDR_CAPABILITIES
|
||||
{
|
||||
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||
|
||||
UINT32 cCapabilitiesSets;
|
||||
CLIPRDR_CAPABILITY_SET* capabilitySets;
|
||||
};
|
||||
typedef struct _CLIPRDR_CAPABILITIES CLIPRDR_CAPABILITIES;
|
||||
|
||||
struct _CLIPRDR_MONITOR_READY
|
||||
{
|
||||
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||
};
|
||||
typedef struct _CLIPRDR_MONITOR_READY CLIPRDR_MONITOR_READY;
|
||||
|
||||
struct _CLIPRDR_FORMAT
|
||||
{
|
||||
UINT32 formatId;
|
||||
char* formatName;
|
||||
};
|
||||
typedef struct _CLIPRDR_FORMAT CLIPRDR_FORMAT;
|
||||
|
||||
struct _CLIPRDR_FORMAT_LIST
|
||||
{
|
||||
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||
|
||||
UINT32 cFormats;
|
||||
CLIPRDR_FORMAT* formats;
|
||||
};
|
||||
typedef struct _CLIPRDR_FORMAT_LIST CLIPRDR_FORMAT_LIST;
|
||||
|
||||
struct _CLIPRDR_FORMAT_LIST_RESPONSE
|
||||
{
|
||||
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||
};
|
||||
typedef struct _CLIPRDR_FORMAT_LIST_RESPONSE CLIPRDR_FORMAT_LIST_RESPONSE;
|
||||
|
||||
struct _CLIPRDR_FORMAT_DATA_REQUEST
|
||||
{
|
||||
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||
|
||||
UINT32 requestedFormatId;
|
||||
};
|
||||
typedef struct _CLIPRDR_FORMAT_DATA_REQUEST CLIPRDR_FORMAT_DATA_REQUEST;
|
||||
|
||||
struct _CLIPRDR_FORMAT_DATA_RESPONSE
|
||||
{
|
||||
DEFINE_CLIPRDR_HEADER_COMMON();
|
||||
|
||||
BYTE* requestedFormatData;
|
||||
};
|
||||
typedef struct _CLIPRDR_FORMAT_DATA_RESPONSE CLIPRDR_FORMAT_DATA_RESPONSE;
|
||||
|
||||
#endif /* FREERDP_CHANNEL_CLIPRDR_H */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Clipboard Virtual Channel Types
|
||||
* Clipboard Virtual Channel Extension
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
*
|
||||
@ -22,72 +22,45 @@
|
||||
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#include <freerdp/message.h>
|
||||
#include <freerdp/channels/cliprdr.h>
|
||||
|
||||
/**
|
||||
* Client Interface
|
||||
*/
|
||||
|
||||
typedef struct _cliprdr_client_context CliprdrClientContext;
|
||||
|
||||
typedef int (*pcCliprdrMonitorReady)(CliprdrClientContext* context);
|
||||
typedef int (*pcCliprdrFormatList)(CliprdrClientContext* context);
|
||||
typedef int (*pcCliprdrDataRequest)(CliprdrClientContext* context);
|
||||
typedef int (*pcCliprdrDataResponse)(CliprdrClientContext* context);
|
||||
typedef int (*pcCliprdrServerCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities);
|
||||
typedef int (*pcCliprdrClientCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities);
|
||||
typedef int (*pcCliprdrMonitorReady)(CliprdrClientContext* context, CLIPRDR_MONITOR_READY* monitorReady);
|
||||
typedef int (*pcCliprdrClientFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList);
|
||||
typedef int (*pcCliprdrServerFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList);
|
||||
typedef int (*pcCliprdrClientFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
|
||||
typedef int (*pcCliprdrServerFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
|
||||
typedef int (*pcCliprdrClientFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
|
||||
typedef int (*pcCliprdrServerFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
|
||||
typedef int (*pcCliprdrClientFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
|
||||
typedef int (*pcCliprdrServerFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
|
||||
|
||||
struct _cliprdr_client_context
|
||||
{
|
||||
void* handle;
|
||||
void* custom;
|
||||
|
||||
pcCliprdrServerCapabilities ServerCapabilities;
|
||||
pcCliprdrClientCapabilities ClientCapabilities;
|
||||
pcCliprdrMonitorReady MonitorReady;
|
||||
pcCliprdrFormatList FormatList;
|
||||
pcCliprdrDataRequest DataRequest;
|
||||
pcCliprdrDataResponse DataResponse;
|
||||
pcCliprdrClientFormatList ClientFormatList;
|
||||
pcCliprdrServerFormatList ServerFormatList;
|
||||
pcCliprdrClientFormatListResponse ClientFormatListResponse;
|
||||
pcCliprdrServerFormatListResponse ServerFormatListResponse;
|
||||
pcCliprdrClientFormatDataRequest ClientFormatDataRequest;
|
||||
pcCliprdrServerFormatDataRequest ServerFormatDataRequest;
|
||||
pcCliprdrClientFormatDataResponse ClientFormatDataResponse;
|
||||
pcCliprdrServerFormatDataResponse ServerFormatDataResponse;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clipboard Formats
|
||||
*/
|
||||
|
||||
#define CB_FORMAT_RAW 0x0000
|
||||
#define CB_FORMAT_TEXT 0x0001
|
||||
#define CB_FORMAT_DIB 0x0008
|
||||
#define CB_FORMAT_UNICODETEXT 0x000D
|
||||
#define CB_FORMAT_HTML 0xD010
|
||||
#define CB_FORMAT_PNG 0xD011
|
||||
#define CB_FORMAT_JPEG 0xD012
|
||||
#define CB_FORMAT_GIF 0xD013
|
||||
|
||||
/* CLIPRDR_HEADER.msgType */
|
||||
#define CB_MONITOR_READY 0x0001
|
||||
#define CB_FORMAT_LIST 0x0002
|
||||
#define CB_FORMAT_LIST_RESPONSE 0x0003
|
||||
#define CB_FORMAT_DATA_REQUEST 0x0004
|
||||
#define CB_FORMAT_DATA_RESPONSE 0x0005
|
||||
#define CB_TEMP_DIRECTORY 0x0006
|
||||
#define CB_CLIP_CAPS 0x0007
|
||||
#define CB_FILECONTENTS_REQUEST 0x0008
|
||||
#define CB_FILECONTENTS_RESPONSE 0x0009
|
||||
#define CB_LOCK_CLIPDATA 0x000A
|
||||
#define CB_UNLOCK_CLIPDATA 0x000B
|
||||
|
||||
/* CLIPRDR_HEADER.msgFlags */
|
||||
#define CB_RESPONSE_OK 0x0001
|
||||
#define CB_RESPONSE_FAIL 0x0002
|
||||
#define CB_ASCII_NAMES 0x0004
|
||||
|
||||
/* CLIPRDR_CAPS_SET.capabilitySetType */
|
||||
#define CB_CAPSTYPE_GENERAL 0x0001
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */
|
||||
#define CB_CAPSTYPE_GENERAL_LEN 12
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.version */
|
||||
#define CB_CAPS_VERSION_1 0x00000001
|
||||
#define CB_CAPS_VERSION_2 0x00000002
|
||||
|
||||
/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
|
||||
#define CB_USE_LONG_FORMAT_NAMES 0x00000002
|
||||
#define CB_STREAM_FILECLIP_ENABLED 0x00000004
|
||||
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008
|
||||
#define CB_CAN_LOCK_CLIPDATA 0x00000010
|
||||
|
||||
struct _CLIPRDR_FORMAT_NAME
|
||||
{
|
||||
UINT32 id;
|
||||
@ -99,10 +72,6 @@ typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME;
|
||||
/**
|
||||
* Clipboard Events
|
||||
*/
|
||||
#define CAPS_USE_LONG_FORMAT_NAMES 0x00000002
|
||||
#define CAPS_STREAM_FILECLIP_ENABLED 0x00000004
|
||||
#define CAPS_FILECLIP_NO_FILE_PATH 0x00000008
|
||||
#define CAPS_CAN_LOCK_CLIPDATA 0x00000010
|
||||
|
||||
struct _RDP_CB_CLIP_CAPS
|
||||
{
|
||||
|
@ -263,10 +263,10 @@
|
||||
#define CliprdrChannel_ClipCaps 5
|
||||
|
||||
#define FREERDP_CLIPRDR_CHANNEL_MONITOR_READY MakeMessageId(CliprdrChannel, MonitorReady)
|
||||
#define FREERDP_CLIPRDR_CHANNEL_FORMAT_LIST MakeMessageId(CliprdrChannel, FormatList)
|
||||
#define FREERDP_CLIPRDR_CHANNEL_FORMAT_LIST MakeMessageId(CliprdrChannel, FormatList)
|
||||
#define FREERDP_CLIPRDR_CHANNEL_DATA_REQUEST MakeMessageId(CliprdrChannel, DataRequest)
|
||||
#define FREERDP_CLIPRDR_CHANNEL_DATA_RESPONSE MakeMessageId(CliprdrChannel, DataResponse)
|
||||
#define FREERDP_CLIPRDR_CHANNEL_CLIP_CAPS MakeMessageId(CliprdrChannel, ClipCaps)
|
||||
#define FREERDP_CLIPRDR_CHANNEL_CLIP_CAPS MakeMessageId(CliprdrChannel, ClipCaps)
|
||||
|
||||
/**
|
||||
* Multimedia Redirection Channel
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
|
||||
#include <freerdp/channels/cliprdr.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
||||
/**
|
||||
|
@ -35,8 +35,36 @@ UINT32 rdpsnd_compute_audio_time_length(AUDIO_FORMAT* format, int size)
|
||||
* http://msdn.microsoft.com/en-us/library/ms713497.aspx
|
||||
*/
|
||||
|
||||
wSamples = (size * 8) / format->wBitsPerSample;
|
||||
mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
|
||||
if (format->wBitsPerSample)
|
||||
{
|
||||
wSamples = (size * 8) / format->wBitsPerSample;
|
||||
mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
|
||||
}
|
||||
else
|
||||
{
|
||||
mstime = 0;
|
||||
|
||||
if (format->wFormatTag == WAVE_FORMAT_GSM610)
|
||||
{
|
||||
UINT16 nSamplesPerBlock;
|
||||
|
||||
if ((format->cbSize == 2) && (format->data))
|
||||
{
|
||||
nSamplesPerBlock = *((UINT16*) format->data);
|
||||
|
||||
wSamples = (size / format->nBlockAlign) * nSamplesPerBlock;
|
||||
mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "rdpsnd_compute_audio_time_length: invalid WAVE_FORMAT_GSM610 format\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "rdpsnd_compute_audio_time_length: unknown format %d\n", format->wFormatTag);
|
||||
}
|
||||
}
|
||||
|
||||
return mstime;
|
||||
}
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <freerdp/event.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#include <freerdp/version.h>
|
||||
#include <freerdp/gdi/gdi.h>
|
||||
|
||||
/* connectErrorCode is 'extern' in error.h. See comment there.*/
|
||||
|
||||
@ -448,8 +447,6 @@ void freerdp_context_free(freerdp* instance)
|
||||
graphics_free(instance->context->graphics);
|
||||
instance->context->graphics = NULL;
|
||||
|
||||
gdi_free(instance);
|
||||
|
||||
PubSub_Free(instance->context->pubSub);
|
||||
|
||||
free(instance->context);
|
||||
|
@ -494,10 +494,9 @@ static void input_free_queued_message(void *obj)
|
||||
|
||||
rdpInput* input_new(rdpRdp* rdp)
|
||||
{
|
||||
wObject cb;
|
||||
const wObject cb = { NULL, NULL, NULL, input_free_queued_message, NULL };
|
||||
rdpInput* input;
|
||||
|
||||
cb.fnObjectFree = input_free_queued_message ;
|
||||
input = (rdpInput*) malloc(sizeof(rdpInput));
|
||||
|
||||
if (input != NULL)
|
||||
|
@ -1553,10 +1553,9 @@ static void update_free_queued_message(void *obj)
|
||||
|
||||
rdpUpdate* update_new(rdpRdp* rdp)
|
||||
{
|
||||
wObject cb;
|
||||
const wObject cb = { NULL, NULL, NULL, update_free_queued_message, NULL };
|
||||
rdpUpdate* update;
|
||||
|
||||
cb.fnObjectFree = update_free_queued_message;
|
||||
update = (rdpUpdate*) malloc(sizeof(rdpUpdate));
|
||||
|
||||
if (update)
|
||||
|
@ -407,7 +407,7 @@ int tls_read(rdpTls* tls, BYTE* data, int length)
|
||||
break;
|
||||
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if (errno == EAGAIN)
|
||||
if ((errno == EAGAIN) || (errno == 0))
|
||||
{
|
||||
status = 0;
|
||||
}
|
||||
@ -603,14 +603,33 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
||||
*/
|
||||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!bio)
|
||||
{
|
||||
fprintf(stderr, "tls_verify_certificate: BIO_new() failure\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = PEM_write_bio_X509(bio, cert->px509);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
fprintf(stderr, "tls_verify_certificate: PEM_write_bio_X509 failure: %d\n", status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
length = 2048;
|
||||
pemCert = (BYTE*) malloc(length + 1);
|
||||
|
||||
status = BIO_read(bio, pemCert, length);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
fprintf(stderr, "tls_verify_certificate: failed to read certificate\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
offset += status;
|
||||
|
||||
while (offset >= length)
|
||||
@ -626,17 +645,27 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
||||
offset += status;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
fprintf(stderr, "tls_verify_certificate: failed to read certificate\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
length = offset;
|
||||
pemCert[length] = '\0';
|
||||
|
||||
status = -1;
|
||||
|
||||
|
||||
if (instance->VerifyX509Certificate)
|
||||
{
|
||||
status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, 0);
|
||||
}
|
||||
|
||||
fprintf(stderr, "VerifyX509Certificate: (length = %d) status: %d\n%s\n",
|
||||
length, status, pemCert);
|
||||
|
||||
free(pemCert);
|
||||
BIO_free(bio);
|
||||
|
||||
return (status < 0) ? FALSE : TRUE;
|
||||
}
|
||||
|
@ -10,28 +10,26 @@
|
||||
# Usage:
|
||||
# android_setup_build_env.sh <source root>
|
||||
|
||||
OPENSSL_SCM=https://github.com/bmiklautz/android-external-openssl-ndk-static
|
||||
OPENSSL_SCM=https://github.com/akallabeth/openssl-android
|
||||
NDK_PROFILER_SCM=https://github.com/richq/android-ndk-profiler
|
||||
|
||||
SCRIPT_NAME=`basename $0`
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
|
||||
echo "Missing command line argument."
|
||||
echo "$SCRIPT_NAME <FreeRDP source>"
|
||||
exit -1
|
||||
echo "Missing command line argument, current directory as root."
|
||||
ROOT=`pwd`
|
||||
ROOT=$ROOT/external
|
||||
else
|
||||
ROOT=`readlink -f $1`
|
||||
fi
|
||||
|
||||
if [ ! -d $1 ]; then
|
||||
echo "Argument '$1' is not a directory."
|
||||
if [ ! -d $ROOT ]; then
|
||||
echo "Argument '$ROOT' is not a directory."
|
||||
exit -2
|
||||
fi
|
||||
SRC=`realpath $1`
|
||||
|
||||
echo "Using '$SRC' as root."
|
||||
echo "Using '$ROOT' as root."
|
||||
|
||||
echo "Preparing OpenSSL..."
|
||||
OPENSSL_SRC=$SRC/external/openssl
|
||||
OPENSSL_SRC=$ROOT/openssl-build
|
||||
if [ -d $OPENSSL_SRC ]; then
|
||||
cd $OPENSSL_SRC
|
||||
git pull
|
||||
@ -39,21 +37,35 @@ if [ -d $OPENSSL_SRC ]; then
|
||||
else
|
||||
git clone $OPENSSL_SCM $OPENSSL_SRC
|
||||
RETVAL=$?
|
||||
cd $OPENSSL_SRC
|
||||
fi
|
||||
if [ $RETVAL -ne 0 ]; then
|
||||
echo "Failed to execute git command [$RETVAL]"
|
||||
exit -3
|
||||
fi
|
||||
ndk-build
|
||||
RETVAL=$?
|
||||
|
||||
cd $OPENSSL_SRC
|
||||
make clean
|
||||
# The makefile has a bug, which aborts during
|
||||
# first compilation. Rerun make to build the whole lib.
|
||||
make
|
||||
make
|
||||
RETVAL=0 # TODO: Check, why 2 is returned.
|
||||
if [ $RETVAL -ne 0 ]; then
|
||||
echo "Failed to execute ndk-build command [$RETVAL]"
|
||||
echo "Failed to execute make command [$RETVAL]"
|
||||
exit -4
|
||||
fi
|
||||
|
||||
# Copy the created library to the default openssl directory,
|
||||
# so that CMake will detect it automatically.
|
||||
SSL_ROOT=`find $OPENSSL_SRC -type d -name "openssl-?.?.*"`
|
||||
rm -f $ROOT/openssl
|
||||
ln -s $SSL_ROOT $ROOT/openssl
|
||||
mkdir -p $ROOT/openssl/obj/local/armeabi/
|
||||
cp $ROOT/openssl/libssl.a $ROOT/openssl/obj/local/armeabi/
|
||||
cp $ROOT/openssl/libcrypto.a $ROOT/openssl/obj/local/armeabi/
|
||||
|
||||
echo "Preparing NDK profiler..."
|
||||
NDK_PROFILER_SRC=$SRC/external/android-ndk-profiler
|
||||
NDK_PROFILER_SRC=$ROOT/android-ndk-profiler
|
||||
if [ -d $NDK_PROFILER_SRC ]; then
|
||||
cd $NDK_PROFILER_SRC
|
||||
git pull
|
||||
@ -61,13 +73,14 @@ if [ -d $NDK_PROFILER_SRC ]; then
|
||||
else
|
||||
git clone $NDK_PROFILER_SCM $NDK_PROFILER_SRC
|
||||
RETVAL=$?
|
||||
cd $NDK_PROFILER_SRC
|
||||
fi
|
||||
if [ $RETVAL -ne 0 ]; then
|
||||
echo "Failed to execute git command [$RETVAL]"
|
||||
exit -5
|
||||
fi
|
||||
ndk-build
|
||||
cd $NDK_PROFILER_SRC
|
||||
ndk-build V=1 APP_ABI=armeabi-v7a clean
|
||||
ndk-build V=1 APP_ABI=armeabi-v7a
|
||||
RETVAL=$?
|
||||
if [ $RETVAL -ne 0 ]; then
|
||||
echo "Failed to execute ndk-build command [$RETVAL]"
|
||||
|
56
scripts/gprof_generate.sh.cmake
Executable file
56
scripts/gprof_generate.sh.cmake
Executable file
@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This script tries to pull gprof profiling information generated by aFreeRDP
|
||||
# from the target using adb and generating human readable profiling data from
|
||||
# it.
|
||||
#
|
||||
# Any arguments supplied to the script will be appended to adb.
|
||||
#
|
||||
# Requirements:
|
||||
# - ANDROID_SDK is set to the android SDK directory or adb is in path.
|
||||
#
|
||||
|
||||
if [ -d $ANDROID_SDK ]; then
|
||||
ADB=$ANDROID_SDK/platform-tools/adb
|
||||
else
|
||||
ADB=`which adb`
|
||||
fi
|
||||
|
||||
GCC=@CMAKE_C_COMPILER@
|
||||
GPROF=${GCC/gcc/gprof}
|
||||
LIB=@CMAKE_BINARY_DIR@/client/Android/FreeRDPCore/jni/armeabi-v7a/libfreerdp-android.so
|
||||
|
||||
if [ ! -f $LIB ]; then
|
||||
echo "Missing libfreerdp-android.so"
|
||||
echo "Please build the project first."
|
||||
exit -1
|
||||
fi
|
||||
|
||||
if [ ! -f $GPROF ]; then
|
||||
echo "gprof could not be found at $GPROF."
|
||||
echo "Please assure, that you are using a GCC based android toolchain."
|
||||
exit -2
|
||||
fi
|
||||
|
||||
if [ ! -f $ADB ] || [ ! -x $ADB ]; then
|
||||
echo "adb could not be found."
|
||||
echo "assure, that either ANDROID_SDK is set to the path of your android SDK"
|
||||
echo "or that adb is in path."
|
||||
exit -3
|
||||
fi
|
||||
|
||||
# Do the acutal work in a temporary directory.
|
||||
SRC=`mktemp -d`
|
||||
cd $SRC
|
||||
$ADB $@ pull /sdcard/gmon.out
|
||||
if [ ! -f gmon.out ]; then
|
||||
echo "Could not pull profiling information from device!"
|
||||
RC=-4
|
||||
else
|
||||
echo "Pulled profiling information from device, starting conversion..."
|
||||
$GPROF $LIB -PprofCount -QprofCount -P__gnu_mcount_nc -Q__gnu_mcount_nc
|
||||
RC=0
|
||||
fi
|
||||
rm -rf $SRC
|
||||
|
||||
exit $RC
|
@ -10,7 +10,7 @@ set(${MODULE_PREFIX}_TESTS
|
||||
TestInitializeSecurityContext.c
|
||||
TestAcquireCredentialsHandle.c
|
||||
TestNTLM.c
|
||||
TestSchannel.c)
|
||||
)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||
${${MODULE_PREFIX}_DRIVER}
|
||||
|
@ -180,13 +180,14 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
||||
pid_t pid;
|
||||
int flags;
|
||||
int numArgs;
|
||||
LPSTR* pArgs;
|
||||
char** envp;
|
||||
LPSTR* pArgs = NULL;
|
||||
char** envp = NULL;
|
||||
char* filename = NULL;
|
||||
WINPR_THREAD* thread;
|
||||
WINPR_PROCESS* process;
|
||||
WINPR_ACCESS_TOKEN* token;
|
||||
LPTCH lpszEnvironmentBlock;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
pid = 0;
|
||||
envp = NULL;
|
||||
@ -210,6 +211,8 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
||||
}
|
||||
|
||||
filename = FindApplicationPath(pArgs[0]);
|
||||
if (NULL == filename)
|
||||
goto finish;
|
||||
|
||||
/* fork and exec */
|
||||
|
||||
@ -218,7 +221,7 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
||||
if (pid < 0)
|
||||
{
|
||||
/* fork failure */
|
||||
return FALSE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
@ -252,7 +255,8 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
||||
|
||||
if (execve(filename, pArgs, envp) < 0)
|
||||
{
|
||||
return FALSE;
|
||||
/* execve failed - end the process */
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -263,7 +267,9 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
||||
process = (WINPR_PROCESS*) malloc(sizeof(WINPR_PROCESS));
|
||||
|
||||
if (!process)
|
||||
return FALSE;
|
||||
{
|
||||
goto finish;
|
||||
}
|
||||
|
||||
ZeroMemory(process, sizeof(WINPR_PROCESS));
|
||||
|
||||
@ -278,7 +284,9 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
||||
ZeroMemory(thread, sizeof(WINPR_THREAD));
|
||||
|
||||
if (!thread)
|
||||
return FALSE;
|
||||
{
|
||||
goto finish;
|
||||
}
|
||||
|
||||
WINPR_HANDLE_SET_TYPE(thread, HANDLE_TYPE_THREAD);
|
||||
|
||||
@ -289,7 +297,13 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
||||
lpProcessInformation->dwProcessId = (DWORD) pid;
|
||||
lpProcessInformation->dwThreadId = (DWORD) pid;
|
||||
|
||||
free(filename);
|
||||
ret = TRUE;
|
||||
|
||||
finish:
|
||||
if (filename)
|
||||
{
|
||||
free(filename);
|
||||
}
|
||||
|
||||
if (pArgs)
|
||||
{
|
||||
@ -312,7 +326,7 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
||||
free(envp);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
|
Loading…
Reference in New Issue
Block a user