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:
Benoît LeBlanc 2013-11-25 14:40:01 -05:00
commit 6a60f79e07
34 changed files with 1208 additions and 377 deletions

View File

@ -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)

View File

@ -213,6 +213,74 @@ void cliprdr_process_long_format_names(cliprdrPlugin* cliprdr, wStream* s, UINT3
void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags)
{
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
if (context->custom)
{
int index;
int formatNameLength;
CLIPRDR_FORMAT* formats;
CLIPRDR_FORMAT_LIST formatList;
formatList.msgType = CB_FORMAT_LIST;
formatList.msgFlags = msgFlags;
formatList.dataLen = dataLen;
formatList.cFormats = 0;
while (dataLen)
{
Stream_Seek(s, 4); /* formatId */
dataLen -= 4;
formatNameLength = _wcslen((WCHAR*) Stream_Pointer(s));
Stream_Seek(s, (formatNameLength + 1) * 2);
dataLen -= ((formatNameLength + 1) * 2);
formatList.cFormats++;
}
index = 0;
dataLen = formatList.dataLen;
Stream_Rewind(s, dataLen);
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;
@ -302,24 +370,58 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
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);
/* http://msdn.microsoft.com/en-us/library/hh872154.aspx */
if (context->custom)
{
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 negociation and data transfer. */
event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
* 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)
{
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
if (context->custom)
{
CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest;
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,
@ -327,6 +429,7 @@ void cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UIN
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,6 +464,30 @@ 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)
{
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
if (context->custom)
{
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;
cb_event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class,
@ -374,4 +501,5 @@ void cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UI
}
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) cb_event);
}
}

View File

@ -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)
{
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
if (context->custom)
{
CLIPRDR_MONITOR_READY monitorReady;
monitorReady.msgType = CB_MONITOR_READY;
monitorReady.msgFlags = flags;
monitorReady.dataLen = length;
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);
event = (RDP_CB_MONITOR_READY_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_MonitorReady, NULL, NULL);
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage *)event);
svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) event);
}
}
static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s)
@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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})

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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,10 +1067,14 @@ 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;
@ -1082,8 +1090,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++)
{
drawRect.origin.x = gdi->primary->hdc->hwnd->cinvalid[i].x;

View File

@ -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,24 +140,37 @@ 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);
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;

View File

@ -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)

View File

@ -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)

View File

@ -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
View 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)

View File

@ -44,6 +44,7 @@
#cmakedefine WITH_PULSE
#cmakedefine WITH_IOSAUDIO
#cmakedefine WITH_OPENSLES
#cmakedefine WITH_GSM
/* Plugins */
#cmakedefine STATIC_CHANNELS

View File

@ -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

View 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 */

View File

@ -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
{

View File

@ -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>
/**

View File

@ -35,8 +35,36 @@ UINT32 rdpsnd_compute_audio_time_length(AUDIO_FORMAT* format, int size)
* http://msdn.microsoft.com/en-us/library/ms713497.aspx
*/
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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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;
}
@ -604,13 +604,32 @@ 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,6 +645,12 @@ 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';
@ -636,7 +661,11 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
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;
}

View File

@ -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
View 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

View File

@ -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}

View File

@ -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;
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,