Update upstream source from tag 'upstream/2.6.0+dfsg1'

Update to upstream version '2.6.0+dfsg1'
with Debian dir e82f2caa6e
This commit is contained in:
Mike Gabriel 2022-02-26 21:44:29 +01:00
commit 4ab6e978fe
59 changed files with 2220 additions and 1519 deletions

View File

@ -41,7 +41,6 @@ addons:
- libgsm1-dev
- libavcodec-dev
- libavutil-dev
- libx264-dev
- libxext-dev
- ninja-build
- libsystemd-dev

View File

@ -85,7 +85,7 @@ if ($ENV{BUILD_NUMBER})
endif()
set(WITH_LIBRARY_VERSIONING "ON")
set(RAW_VERSION_STRING "2.5.0")
set(RAW_VERSION_STRING "2.6.0")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)
@ -652,6 +652,7 @@ if(UNIX OR CYGWIN)
include(CheckFunctionExists)
check_function_exists(getlogin_r HAVE_GETLOGIN_R)
check_function_exists(getpwuid_r HAVE_GETPWUID_R)
else()
set(X11_FEATURE_TYPE "DISABLED")
set(WAYLAND_FEATURE_TYPE "DISABLED")
@ -719,10 +720,6 @@ set(JPEG_FEATURE_TYPE "OPTIONAL")
set(JPEG_FEATURE_PURPOSE "codec")
set(JPEG_FEATURE_DESCRIPTION "use JPEG library")
set(X264_FEATURE_TYPE "OPTIONAL")
set(X264_FEATURE_PURPOSE "codec")
set(X264_FEATURE_DESCRIPTION "use x264 library")
set(OPENH264_FEATURE_TYPE "OPTIONAL")
set(OPENH264_FEATURE_PURPOSE "codec")
set(OPENH264_FEATURE_DESCRIPTION "use OpenH264 library")
@ -808,7 +805,6 @@ if(ANDROID)
set(PULSE_FEATURE_TYPE "DISABLED")
set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "DISABLED")
set(VAAPI_FEATURE_TYPE "DISABLED")
set(OPENSLES_FEATURE_TYPE "REQUIRED")
endif()
@ -831,7 +827,6 @@ find_feature(PCSC ${PCSC_FEATURE_TYPE} ${PCSC_FEATURE_PURPOSE} ${PCSC_FEATURE_DE
find_feature(FFmpeg ${FFMPEG_FEATURE_TYPE} ${FFMPEG_FEATURE_PURPOSE} ${FFMPEG_FEATURE_DESCRIPTION})
find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DESCRIPTION})
find_feature(x264 ${X264_FEATURE_TYPE} ${X264_FEATURE_PURPOSE} ${X264_FEATURE_DESCRIPTION})
find_feature(OpenH264 ${OPENH264_FEATURE_TYPE} ${OPENH264_FEATURE_PURPOSE} ${OPENH264_FEATURE_DESCRIPTION})
find_feature(OpenCL ${OPENCL_FEATURE_TYPE} ${OPENCL_FEATURE_PURPOSE} ${OPENCL_FEATURE_DESCRIPTION})
find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION})
@ -917,7 +912,7 @@ if(MBEDTLS_FOUND)
add_definitions("-DWITH_MBEDTLS")
endif()
if (WITH_X264 OR WITH_OPENH264 OR WITH_MEDIA_FOUNDATION OR WITH_FFMPEG)
if (WITH_OPENH264 OR WITH_MEDIA_FOUNDATION OR WITH_FFMPEG OR WITH_MEDIACODEC)
set(WITH_GFX_H264 ON)
else()
set(WITH_GFX_H264 OFF)

View File

@ -1,3 +1,26 @@
# 2022-02-22 Version 2.6.0
Noteworthy changes:
* Backported android FFMPEG build scripts
* Updated android build dependencies
Fixed issues:
* Backported #7303: Fix PDU length for RDPINPUT_PROTOCOL_V300
* Backported #7658: Sanitize optional physical monitor size values
* Backported #7426: Wayland memory corruption
* Backported #7293: Remove unused codec x264
* Backported #7541: Allow resolutions larger 2048x2048
* Backported #7574: FFMPEG 5.0 support
* Backported #7578: FFMPEG 5.0 support
* Backported #7580: Fixed device hotplugging
* Backported #7583: GetUserNameExA: Prefer getpwuid_r over getlogin_r over getlogin
* Backported #7585: Android Mediacodec support
Important notes:
For a complete and detailed change log since the last release run:
git log 2.5.0..2.6.0
# 2022-01-12 Version 2.5.0
Noteworthy changes:

View File

@ -1,7 +1,8 @@
# FreeRDP cmake android options
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2013 Thincast Technologies GmbH
# Copyright 2013 Bernhard Miklautz <bernhard.miklautz@thincast.com>
# Copyright 2022 Armin Novak <anovak@thincast.com>
# Copyright 2022 Thincast Technologies GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -15,8 +16,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
option(WITH_OPENSLES "Enable sound and microphone redirection using OpenSLES" ON)
define_channel("ainput")
set(ANDROID_APP_TARGET_SDK 21 CACHE STRING "Application target android SDK")
set(ANDROID_APP_MIN_SDK 14 CACHE STRING "Application minimum android SDK requirement")
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -0,0 +1,13 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT ON)
define_channel_options(NAME "ainput" TYPE "dynamic"
DESCRIPTION "Advanced Input Virtual Channel Extension"
SPECIFICATIONS "[XXXXX]"
DEFAULT ${OPTION_DEFAULT})
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})

View File

@ -0,0 +1,34 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2022 Armin Novak <anovak@thincast.com>
# Copyright 2022 Thincast Technologies GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
define_channel_client("ainput")
set(${MODULE_PREFIX}_SRCS
ainput_main.c
ainput_main.h)
include_directories(..)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT BUILTIN_CHANNELS AND BUILD_SHARED_LIBS)
install(FILES ${PROJECT_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${FREERDP_ADDIN_PATH} COMPONENT symbols)
endif()
target_link_libraries(${MODULE_NAME} winpr)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -0,0 +1,317 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Advanced Input Virtual Channel Extension
*
* Copyright 2022 Armin Novak <anovak@thincast.com>
* Copyright 2022 Thincast Technologies GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <winpr/crt.h>
#include <assert.h>
#include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include "ainput_main.h"
#include <freerdp/channels/log.h>
#include <freerdp/client/ainput.h>
#include <freerdp/channels/ainput.h>
#include "../common/ainput_common.h"
#define WINPR_ASSERT(x) assert(x)
#define TAG CHANNELS_TAG("ainput.client")
typedef struct AINPUT_CHANNEL_CALLBACK_ AINPUT_CHANNEL_CALLBACK;
struct AINPUT_CHANNEL_CALLBACK_
{
IWTSVirtualChannelCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
IWTSVirtualChannel* channel;
};
typedef struct AINPUT_LISTENER_CALLBACK_ AINPUT_LISTENER_CALLBACK;
struct AINPUT_LISTENER_CALLBACK_
{
IWTSListenerCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
AINPUT_CHANNEL_CALLBACK* channel_callback;
};
typedef struct AINPUT_PLUGIN_ AINPUT_PLUGIN;
struct AINPUT_PLUGIN_
{
IWTSPlugin iface;
AINPUT_LISTENER_CALLBACK* listener_callback;
IWTSListener* listener;
UINT32 MajorVersion;
UINT32 MinorVersion;
BOOL initialized;
};
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT ainput_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data)
{
UINT16 type;
AINPUT_PLUGIN* ainput;
AINPUT_CHANNEL_CALLBACK* callback = (AINPUT_CHANNEL_CALLBACK*)pChannelCallback;
WINPR_ASSERT(callback);
WINPR_ASSERT(data);
ainput = (AINPUT_PLUGIN*)callback->plugin;
WINPR_ASSERT(ainput);
if (Stream_GetRemainingLength(data) < 2)
return ERROR_NO_DATA;
Stream_Read_UINT16(data, type);
switch (type)
{
case MSG_AINPUT_VERSION:
if (Stream_GetRemainingLength(data) < 8)
return ERROR_NO_DATA;
Stream_Read_UINT32(data, ainput->MajorVersion);
Stream_Read_UINT32(data, ainput->MinorVersion);
break;
default:
WLog_WARN(TAG, "Received unsupported message type 0x%04" PRIx16, type);
break;
}
return CHANNEL_RC_OK;
}
static UINT ainput_send_input_event(AInputClientContext* context, UINT64 flags, INT32 x, INT32 y)
{
AINPUT_PLUGIN* ainput;
AINPUT_CHANNEL_CALLBACK* callback;
BYTE buffer[32] = { 0 };
UINT64 time;
wStream sbuffer = { 0 };
wStream* s = &sbuffer;
Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
WINPR_ASSERT(s);
WINPR_ASSERT(context);
time = GetTickCount64();
ainput = (AINPUT_PLUGIN*)context->handle;
WINPR_ASSERT(ainput);
WINPR_ASSERT(ainput->listener_callback);
if (ainput->MajorVersion != AINPUT_VERSION_MAJOR)
{
WLog_WARN(TAG, "Unsupported channel version %" PRIu32 ".%" PRIu32 ", aborting.",
ainput->MajorVersion, ainput->MinorVersion);
return CHANNEL_RC_UNSUPPORTED_VERSION;
}
callback = ainput->listener_callback->channel_callback;
WINPR_ASSERT(callback);
{
char buffer[128] = { 0 };
WLog_VRB(TAG, "[%s] sending timestamp=0x%08" PRIx64 ", flags=%s, %" PRId32 "x%" PRId32,
__FUNCTION__, time, ainput_flags_to_string(flags, buffer, sizeof(buffer)), x, y);
}
/* Message type */
Stream_Write_UINT16(s, MSG_AINPUT_MOUSE);
/* Event data */
Stream_Write_UINT64(s, time);
Stream_Write_UINT64(s, flags);
Stream_Write_INT32(s, x);
Stream_Write_INT32(s, y);
Stream_SealLength(s);
/* ainput back what we have received. AINPUT does not have any message IDs. */
WINPR_ASSERT(callback->channel);
WINPR_ASSERT(callback->channel->Write);
return callback->channel->Write(callback->channel, (ULONG)Stream_Length(s), Stream_Buffer(s),
NULL);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT ainput_on_close(IWTSVirtualChannelCallback* pChannelCallback)
{
AINPUT_CHANNEL_CALLBACK* callback = (AINPUT_CHANNEL_CALLBACK*)pChannelCallback;
free(callback);
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT ainput_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
IWTSVirtualChannel* pChannel, BYTE* Data,
BOOL* pbAccept,
IWTSVirtualChannelCallback** ppCallback)
{
AINPUT_CHANNEL_CALLBACK* callback;
AINPUT_LISTENER_CALLBACK* listener_callback = (AINPUT_LISTENER_CALLBACK*)pListenerCallback;
WINPR_ASSERT(listener_callback);
WINPR_UNUSED(Data);
WINPR_UNUSED(pbAccept);
callback = (AINPUT_CHANNEL_CALLBACK*)calloc(1, sizeof(AINPUT_CHANNEL_CALLBACK));
if (!callback)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
callback->iface.OnDataReceived = ainput_on_data_received;
callback->iface.OnClose = ainput_on_close;
callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel;
listener_callback->channel_callback = callback;
*ppCallback = &callback->iface;
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT ainput_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{
UINT status;
AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)pPlugin;
WINPR_ASSERT(ainput);
if (ainput->initialized)
{
WLog_ERR(TAG, "[%s] channel initialized twice, aborting", AINPUT_DVC_CHANNEL_NAME);
return ERROR_INVALID_DATA;
}
ainput->listener_callback =
(AINPUT_LISTENER_CALLBACK*)calloc(1, sizeof(AINPUT_LISTENER_CALLBACK));
if (!ainput->listener_callback)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
ainput->listener_callback->iface.OnNewChannelConnection = ainput_on_new_channel_connection;
ainput->listener_callback->plugin = pPlugin;
ainput->listener_callback->channel_mgr = pChannelMgr;
status = pChannelMgr->CreateListener(pChannelMgr, AINPUT_DVC_CHANNEL_NAME, 0,
&ainput->listener_callback->iface, &ainput->listener);
ainput->listener->pInterface = ainput->iface.pInterface;
ainput->initialized = status == CHANNEL_RC_OK;
return status;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT ainput_plugin_terminated(IWTSPlugin* pPlugin)
{
AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)pPlugin;
if (ainput && ainput->listener_callback)
{
IWTSVirtualChannelManager* mgr = ainput->listener_callback->channel_mgr;
if (mgr)
IFCALL(mgr->DestroyListener, mgr, ainput->listener);
}
if (ainput)
{
free(ainput->listener_callback);
free(ainput->iface.pInterface);
}
free(ainput);
return CHANNEL_RC_OK;
}
#ifdef BUILTIN_CHANNELS
#define DVCPluginEntry ainput_DVCPluginEntry
#else
#define DVCPluginEntry FREERDP_API DVCPluginEntry
#endif
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
UINT status = CHANNEL_RC_OK;
AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, "ainput");
if (!ainput)
{
AInputClientContext* context = (AInputClientContext*)calloc(1, sizeof(AInputClientContext));
ainput = (AINPUT_PLUGIN*)calloc(1, sizeof(AINPUT_PLUGIN));
if (!ainput || !context)
{
free(context);
free(ainput);
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
ainput->iface.Initialize = ainput_plugin_initialize;
ainput->iface.Terminated = ainput_plugin_terminated;
context->handle = (void*)ainput;
context->AInputSendInputEvent = ainput_send_input_event;
ainput->iface.pInterface = (void*)context;
status = pEntryPoints->RegisterPlugin(pEntryPoints, AINPUT_CHANNEL_NAME, &ainput->iface);
}
return status;
}

View File

@ -0,0 +1,43 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Advanced Input Virtual Channel Extension
*
* Copyright 2022 Armin Novak <anovak@thincast.com>
* Copyright 2022 Thincast Technologies GmbH
*
* 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_AINPUT_CLIENT_MAIN_H
#define FREERDP_CHANNEL_AINPUT_CLIENT_MAIN_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <freerdp/dvc.h>
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <freerdp/channels/log.h>
#define DVC_TAG CHANNELS_TAG("ainput.client")
#ifdef WITH_DEBUG_DVC
#define DEBUG_DVC(...) WLog_DBG(DVC_TAG, __VA_ARGS__)
#else
#define DEBUG_DVC(...) \
do \
{ \
} while (0)
#endif
#endif /* FREERDP_CHANNEL_AINPUT_CLIENT_MAIN_H */

View File

@ -0,0 +1,81 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Audio Input Redirection Virtual Channel
*
* Copyright 2022 Armin Novak <anovak@thincast.com>
* Copyright 2022 Thincast Technologies GmbH
*
* 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_INT_AINPUT_COMMON_H
#define FREERDP_INT_AINPUT_COMMON_H
#include <assert.h>
#include <winpr/string.h>
#include <freerdp/channels/ainput.h>
static INLINE void ainput_append(char* buffer, size_t size, const char* what, BOOL separator)
{
size_t have;
size_t toadd;
assert(buffer || (size == 0));
assert(what);
have = strnlen(buffer, size);
toadd = strlen(what);
if (have > 0)
toadd += 1;
if (size - have < toadd + 1)
return;
if (have > 0)
strcat(buffer, separator ? "|" : " ");
strcat(buffer, what);
}
static INLINE const char* ainput_flags_to_string(UINT64 flags, char* buffer, size_t size)
{
char number[32] = { 0 };
if (flags & AINPUT_FLAGS_HAVE_REL)
ainput_append(buffer, size, "AINPUT_FLAGS_HAVE_REL", TRUE);
if (flags & AINPUT_FLAGS_WHEEL)
ainput_append(buffer, size, "AINPUT_FLAGS_WHEEL", TRUE);
if (flags & AINPUT_FLAGS_MOVE)
ainput_append(buffer, size, "AINPUT_FLAGS_MOVE", TRUE);
if (flags & AINPUT_FLAGS_DOWN)
ainput_append(buffer, size, "AINPUT_FLAGS_DOWN", TRUE);
if (flags & AINPUT_FLAGS_REL)
ainput_append(buffer, size, "AINPUT_FLAGS_REL", TRUE);
if (flags & AINPUT_FLAGS_BUTTON1)
ainput_append(buffer, size, "AINPUT_FLAGS_BUTTON1", TRUE);
if (flags & AINPUT_FLAGS_BUTTON2)
ainput_append(buffer, size, "AINPUT_FLAGS_BUTTON2", TRUE);
if (flags & AINPUT_FLAGS_BUTTON3)
ainput_append(buffer, size, "AINPUT_FLAGS_BUTTON3", TRUE);
if (flags & AINPUT_XFLAGS_BUTTON1)
ainput_append(buffer, size, "AINPUT_XFLAGS_BUTTON1", TRUE);
if (flags & AINPUT_XFLAGS_BUTTON2)
ainput_append(buffer, size, "AINPUT_XFLAGS_BUTTON2", TRUE);
_snprintf(number, sizeof(number), "[0x%08" PRIx64 "]", flags);
ainput_append(buffer, size, number, FALSE);
return buffer;
}
#endif /* FREERDP_INT_AINPUT_COMMON_H */

View File

@ -0,0 +1,27 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2022 Armin Novak <anovak@thincast.com>
# Copyright 2022 Thincast Technologies GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
define_channel_server("ainput")
set(${MODULE_PREFIX}_SRCS
ainput_main.c)
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "DVCPluginEntry")
target_link_libraries(${MODULE_NAME} freerdp)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -0,0 +1,546 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Advanced Input Virtual Channel Extension
*
* Copyright 2022 Armin Novak <anovak@thincast.com>
* Copyright 2022 Thincast Technologies GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <assert.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include <freerdp/server/ainput.h>
#include <freerdp/channels/ainput.h>
#include <freerdp/channels/log.h>
#include "../common/ainput_common.h"
#define WINPR_ASSERT(x) assert(x)
#define TAG CHANNELS_TAG("ainput.server")
typedef enum
{
AINPUT_INITIAL,
AINPUT_OPENED,
AINPUT_VERSION_SENT,
} eAInputChannelState;
typedef struct
{
ainput_server_context context;
BOOL opened;
HANDLE stopEvent;
HANDLE thread;
void* ainput_channel;
DWORD SessionId;
BOOL isOpened;
BOOL externalThread;
/* Channel state */
eAInputChannelState state;
wStream* buffer;
} ainput_server;
static UINT ainput_server_context_poll(ainput_server_context* context);
static BOOL ainput_server_context_handle(ainput_server_context* context, HANDLE* handle);
static UINT ainput_server_context_poll_int(ainput_server_context* context);
static BOOL ainput_server_is_open(ainput_server_context* context)
{
ainput_server* ainput = (ainput_server*)context;
WINPR_ASSERT(ainput);
return ainput->isOpened;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT ainput_server_open_channel(ainput_server* ainput)
{
DWORD Error;
HANDLE hEvent;
DWORD StartTick;
DWORD BytesReturned = 0;
PULONG pSessionId = NULL;
WINPR_ASSERT(ainput);
if (WTSQuerySessionInformationA(ainput->context.vcm, WTS_CURRENT_SESSION, WTSSessionId,
(LPSTR*)&pSessionId, &BytesReturned) == FALSE)
{
WLog_ERR(TAG, "WTSQuerySessionInformationA failed!");
return ERROR_INTERNAL_ERROR;
}
ainput->SessionId = (DWORD)*pSessionId;
WTSFreeMemory(pSessionId);
hEvent = WTSVirtualChannelManagerGetEventHandle(ainput->context.vcm);
StartTick = GetTickCount();
while (ainput->ainput_channel == NULL)
{
if (WaitForSingleObject(hEvent, 1000) == WAIT_FAILED)
{
Error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", Error);
return Error;
}
ainput->ainput_channel = WTSVirtualChannelOpenEx(ainput->SessionId, AINPUT_DVC_CHANNEL_NAME,
WTS_CHANNEL_OPTION_DYNAMIC);
if (ainput->ainput_channel)
break;
Error = GetLastError();
if (Error == ERROR_NOT_FOUND)
break;
if (GetTickCount() - StartTick > 5000)
break;
}
return ainput->ainput_channel ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
}
static UINT ainput_server_send_version(ainput_server* ainput)
{
ULONG written;
wStream* s;
WINPR_ASSERT(ainput);
s = ainput->buffer;
WINPR_ASSERT(s);
Stream_SetPosition(s, 0);
if (!Stream_EnsureCapacity(s, 10))
return ERROR_OUTOFMEMORY;
Stream_Write_UINT16(s, MSG_AINPUT_VERSION);
Stream_Write_UINT32(s, AINPUT_VERSION_MAJOR); /* Version (4 bytes) */
Stream_Write_UINT32(s, AINPUT_VERSION_MINOR); /* Version (4 bytes) */
WINPR_ASSERT(Stream_GetPosition(s) <= ULONG_MAX);
if (!WTSVirtualChannelWrite(ainput->ainput_channel, (PCHAR)Stream_Buffer(s),
(ULONG)Stream_GetPosition(s), &written))
{
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
}
static UINT ainput_server_recv_mouse_event(ainput_server* ainput, wStream* s)
{
UINT error = CHANNEL_RC_OK;
UINT64 flags, time;
INT32 x, y;
char buffer[128] = { 0 };
WINPR_ASSERT(ainput);
WINPR_ASSERT(s);
if (Stream_GetRemainingLength(s) < 24)
return ERROR_NO_DATA;
Stream_Read_UINT64(s, time);
Stream_Read_UINT64(s, flags);
Stream_Read_INT32(s, x);
Stream_Read_INT32(s, y);
WLog_VRB(TAG, "[%s] received: time=0x%08" PRIx64 ", flags=%s, %" PRId32 "x%" PRId32,
__FUNCTION__, time, ainput_flags_to_string(flags, buffer, sizeof(buffer)), x, y);
IFCALLRET(ainput->context.MouseEvent, error, &ainput->context, time, flags, x, y);
return error;
}
static HANDLE ainput_server_get_channel_handle(ainput_server* ainput)
{
BYTE* buffer = NULL;
DWORD BytesReturned = 0;
HANDLE ChannelEvent = NULL;
WINPR_ASSERT(ainput);
if (WTSVirtualChannelQuery(ainput->ainput_channel, WTSVirtualEventHandle, &buffer,
&BytesReturned) == TRUE)
{
if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
}
return ChannelEvent;
}
static DWORD WINAPI ainput_server_thread_func(LPVOID arg)
{
DWORD nCount;
HANDLE events[2] = { 0 };
ainput_server* ainput = (ainput_server*)arg;
UINT error = CHANNEL_RC_OK;
DWORD status;
WINPR_ASSERT(ainput);
nCount = 0;
events[nCount++] = ainput->stopEvent;
while ((error == CHANNEL_RC_OK) && (WaitForSingleObject(events[0], 0) != WAIT_OBJECT_0))
{
switch (ainput->state)
{
case AINPUT_OPENED:
events[1] = ainput_server_get_channel_handle(ainput);
nCount = 2;
status = WaitForMultipleObjects(nCount, events, FALSE, 100);
switch (status)
{
case WAIT_TIMEOUT:
case WAIT_OBJECT_0 + 1:
case WAIT_OBJECT_0:
error = ainput_server_context_poll_int(&ainput->context);
case WAIT_FAILED:
default:
error = ERROR_INTERNAL_ERROR;
break;
}
break;
case AINPUT_VERSION_SENT:
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
switch (status)
{
case WAIT_TIMEOUT:
case WAIT_OBJECT_0 + 1:
case WAIT_OBJECT_0:
error = ainput_server_context_poll_int(&ainput->context);
case WAIT_FAILED:
default:
error = ERROR_INTERNAL_ERROR;
break;
}
break;
default:
error = ainput_server_context_poll_int(&ainput->context);
break;
}
}
WTSVirtualChannelClose(ainput->ainput_channel);
ainput->ainput_channel = NULL;
if (error && ainput->context.rdpcontext)
setChannelError(ainput->context.rdpcontext, error,
"ainput_server_thread_func reported an error");
ExitThread(error);
return error;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT ainput_server_open(ainput_server_context* context)
{
ainput_server* ainput = (ainput_server*)context;
WINPR_ASSERT(ainput);
if (!ainput->externalThread && (ainput->thread == NULL))
{
ainput->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!ainput->stopEvent)
{
WLog_ERR(TAG, "CreateEvent failed!");
return ERROR_INTERNAL_ERROR;
}
ainput->thread = CreateThread(NULL, 0, ainput_server_thread_func, ainput, 0, NULL);
if (!ainput->thread)
{
WLog_ERR(TAG, "CreateEvent failed!");
CloseHandle(ainput->stopEvent);
ainput->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
}
ainput->isOpened = TRUE;
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT ainput_server_close(ainput_server_context* context)
{
UINT error = CHANNEL_RC_OK;
ainput_server* ainput = (ainput_server*)context;
WINPR_ASSERT(ainput);
if (!ainput->externalThread && ainput->thread)
{
SetEvent(ainput->stopEvent);
if (WaitForSingleObject(ainput->thread, INFINITE) == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error);
return error;
}
CloseHandle(ainput->thread);
CloseHandle(ainput->stopEvent);
ainput->thread = NULL;
ainput->stopEvent = NULL;
}
if (ainput->externalThread)
{
if (ainput->state != AINPUT_INITIAL)
{
WTSVirtualChannelClose(ainput->ainput_channel);
ainput->ainput_channel = NULL;
ainput->state = AINPUT_INITIAL;
}
}
ainput->isOpened = FALSE;
return error;
}
static UINT ainput_server_initialize(ainput_server_context* context, BOOL externalThread)
{
UINT error = CHANNEL_RC_OK;
ainput_server* ainput = (ainput_server*)context;
WINPR_ASSERT(ainput);
if (ainput->isOpened)
{
WLog_WARN(TAG, "Application error: AINPUT channel already initialized, calling in this "
"state is not possible!");
return ERROR_INVALID_STATE;
}
ainput->externalThread = externalThread;
return error;
}
ainput_server_context* ainput_server_context_new(HANDLE vcm)
{
ainput_server* ainput = (ainput_server*)calloc(1, sizeof(ainput_server));
if (!ainput)
return NULL;
ainput->context.vcm = vcm;
ainput->context.Open = ainput_server_open;
ainput->context.IsOpen = ainput_server_is_open;
ainput->context.Close = ainput_server_close;
ainput->context.Initialize = ainput_server_initialize;
ainput->context.Poll = ainput_server_context_poll;
ainput->context.ChannelHandle = ainput_server_context_handle;
ainput->buffer = Stream_New(NULL, 4096);
if (!ainput->buffer)
goto fail;
return &ainput->context;
fail:
ainput_server_context_free(ainput);
return NULL;
}
void ainput_server_context_free(ainput_server_context* context)
{
ainput_server* ainput = (ainput_server*)context;
if (ainput)
{
ainput_server_close(context);
Stream_Free(ainput->buffer, TRUE);
}
free(ainput);
}
static UINT ainput_process_message(ainput_server* ainput)
{
BOOL rc;
UINT error = ERROR_INTERNAL_ERROR;
ULONG BytesReturned;
UINT16 MessageId;
wStream* s;
WINPR_ASSERT(ainput);
WINPR_ASSERT(ainput->ainput_channel);
s = ainput->buffer;
WINPR_ASSERT(s);
Stream_SetPosition(s, 0);
rc = WTSVirtualChannelRead(ainput->ainput_channel, 0, NULL, 0, &BytesReturned);
if (!rc)
goto out;
if (BytesReturned < 2)
{
error = CHANNEL_RC_OK;
goto out;
}
if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
error = CHANNEL_RC_NO_MEMORY;
goto out;
}
if (WTSVirtualChannelRead(ainput->ainput_channel, 0, (PCHAR)Stream_Buffer(s),
(ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
goto out;
}
Stream_SetLength(s, BytesReturned);
Stream_Read_UINT16(s, MessageId);
switch (MessageId)
{
case MSG_AINPUT_MOUSE:
error = ainput_server_recv_mouse_event(ainput, s);
break;
default:
WLog_ERR(TAG, "audin_server_thread_func: unknown MessageId %" PRIu8 "", MessageId);
break;
}
out:
if (error)
WLog_ERR(TAG, "Response failed with error %" PRIu32 "!", error);
return error;
}
BOOL ainput_server_context_handle(ainput_server_context* context, HANDLE* handle)
{
ainput_server* ainput = (ainput_server*)context;
WINPR_ASSERT(ainput);
WINPR_ASSERT(handle);
if (!ainput->externalThread)
return FALSE;
if (ainput->state == AINPUT_INITIAL)
return FALSE;
*handle = ainput_server_get_channel_handle(ainput);
return TRUE;
}
UINT ainput_server_context_poll_int(ainput_server_context* context)
{
ainput_server* ainput = (ainput_server*)context;
UINT error = ERROR_INTERNAL_ERROR;
WINPR_ASSERT(ainput);
switch (ainput->state)
{
case AINPUT_INITIAL:
error = ainput_server_open_channel(ainput);
if (error)
WLog_ERR(TAG, "ainput_server_open_channel failed with error %" PRIu32 "!", error);
else
ainput->state = AINPUT_OPENED;
break;
case AINPUT_OPENED:
{
BYTE* buffer = NULL;
DWORD BytesReturned = 0;
if (WTSVirtualChannelQuery(ainput->ainput_channel, WTSVirtualChannelReady, &buffer,
&BytesReturned) != TRUE)
{
WLog_ERR(TAG, "WTSVirtualChannelReady failed,");
}
else
{
if (*buffer != 0)
{
error = ainput_server_send_version(ainput);
if (error)
WLog_ERR(TAG, "audin_server_send_version failed with error %" PRIu32 "!",
error);
else
ainput->state = AINPUT_VERSION_SENT;
}
else
error = CHANNEL_RC_OK;
}
WTSFreeMemory(buffer);
}
break;
case AINPUT_VERSION_SENT:
error = ainput_process_message(ainput);
break;
default:
WLog_ERR(TAG, "AINPUT chanel is in invalid state %d", ainput->state);
break;
}
return error;
}
UINT ainput_server_context_poll(ainput_server_context* context)
{
ainput_server* ainput = (ainput_server*)context;
WINPR_ASSERT(ainput);
if (!ainput->externalThread)
return ERROR_INTERNAL_ERROR;
return ainput_server_context_poll_int(context);
}

View File

@ -444,11 +444,8 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb
return FALSE;
}
if (!supported)
{
if (!freerdp_dsp_context_reset(audin->dsp_context, audin->format))
return FALSE;
}
if (!freerdp_dsp_context_reset(audin->dsp_context, audin->format))
return FALSE;
IFCALLRET(audin->device->Open, error, audin->device, audin_receive_wave_data, callback);

View File

@ -345,7 +345,9 @@ static UINT audin_winmm_set_format(IAudinDevice* device, const AUDIO_FORMAT* for
if (ppwfx->nBlockAlign != 2)
{
ppwfx->nBlockAlign = 2;
ppwfx->nAvgBytesPerSec = ppwfx->nSamplesPerSec * ppwfx->nBlockAlign;
}
if (!test_format_supported(ppwfx))
return ERROR_INVALID_PARAMETER;
winmm->pwfx_cur = ppwfx;

View File

@ -72,6 +72,24 @@ error:
return NULL;
}
static void disp_server_sanitize_monitor_layout(DISPLAY_CONTROL_MONITOR_LAYOUT* monitor)
{
if (monitor->PhysicalWidth < DISPLAY_CONTROL_MIN_PHYSICAL_MONITOR_WIDTH ||
monitor->PhysicalWidth > DISPLAY_CONTROL_MAX_PHYSICAL_MONITOR_WIDTH ||
monitor->PhysicalHeight < DISPLAY_CONTROL_MIN_PHYSICAL_MONITOR_HEIGHT ||
monitor->PhysicalHeight > DISPLAY_CONTROL_MAX_PHYSICAL_MONITOR_HEIGHT)
{
if (monitor->PhysicalWidth != 0 || monitor->PhysicalHeight != 0)
WLog_DBG(
TAG,
"Sanitizing invalid physical monitor size. Old physical monitor size: [%" PRIu32
", %" PRIu32 "]",
monitor->PhysicalWidth, monitor->PhysicalHeight);
monitor->PhysicalWidth = monitor->PhysicalHeight = 0;
}
}
static BOOL disp_server_is_monitor_layout_valid(DISPLAY_CONTROL_MONITOR_LAYOUT* monitor)
{
if (monitor->Width < DISPLAY_CONTROL_MIN_MONITOR_WIDTH ||
@ -88,22 +106,6 @@ static BOOL disp_server_is_monitor_layout_valid(DISPLAY_CONTROL_MONITOR_LAYOUT*
return FALSE;
}
if (monitor->PhysicalWidth < DISPLAY_CONTROL_MIN_PHYSICAL_MONITOR_WIDTH ||
monitor->PhysicalWidth > DISPLAY_CONTROL_MAX_PHYSICAL_MONITOR_WIDTH)
{
WLog_WARN(TAG, "Received invalid value for monitor->PhysicalWidth: %" PRIu32 "",
monitor->PhysicalWidth);
return FALSE;
}
if (monitor->PhysicalHeight < DISPLAY_CONTROL_MIN_PHYSICAL_MONITOR_HEIGHT ||
monitor->PhysicalHeight > DISPLAY_CONTROL_MAX_PHYSICAL_MONITOR_HEIGHT)
{
WLog_WARN(TAG, "Received invalid value for monitor->Height: %" PRIu32 "",
monitor->PhysicalHeight);
return FALSE;
}
switch (monitor->Orientation)
{
case ORIENTATION_LANDSCAPE:
@ -183,6 +185,8 @@ static UINT disp_recv_display_control_monitor_layout_pdu(wStream* s, DispServerC
Stream_Read_UINT32(s, monitor->Orientation); /* Orientation (4 bytes) */
Stream_Read_UINT32(s, monitor->DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */
Stream_Read_UINT32(s, monitor->DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */
disp_server_sanitize_monitor_layout(monitor);
WLog_DBG(TAG,
"\t%d : Flags: 0x%08" PRIX32 " Left/Top: (%" PRId32 ",%" PRId32 ") W/H=%" PRIu32
"x%" PRIu32 ")",

View File

@ -33,6 +33,8 @@
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <winpr/sspicli.h>
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <freerdp/channels/log.h>
@ -204,7 +206,6 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
drive.Type = RDPDR_DTYP_FILESYSTEM;
drive.Path = drive_path;
drive_path[1] = '\0';
drive.automount = TRUE;
drive.Name = drive_name;
devman_load_device_service(rdpdr->devman,
@ -583,7 +584,6 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
#else
static const char* automountLocations[] = { "/run/user/%lu/gvfs", "/run/media/%s", "/media/%s",
"/media", "/mnt" };
@ -591,16 +591,13 @@ static BOOL isAutomountLocation(const char* path)
{
const size_t nrLocations = sizeof(automountLocations) / sizeof(automountLocations[0]);
size_t x;
char buffer[MAX_PATH];
char buffer[MAX_PATH] = { 0 };
uid_t uid = getuid();
char uname[MAX_PATH] = { 0 };
ULONG size = sizeof(uname) - 1;
#ifndef HAVE_GETLOGIN_R
strncpy(uname, getlogin(), sizeof(uname));
#else
if (getlogin_r(uname, sizeof(uname)) != 0)
if (!GetUserNameExA(NameSamCompatible, uname, &size))
return FALSE;
#endif
if (!path)
return FALSE;
@ -656,7 +653,7 @@ static void handle_mountpoint(hotplug_dev* dev_array, size_t* size, const char*
if (isAutomountLocation(mountpoint) && (*size < MAX_USB_DEVICES))
{
dev_array[*size].path = _strdup(mountpoint);
dev_array[*size + 1].to_add = TRUE;
dev_array[*size].to_add = TRUE;
(*size)++;
}
}

View File

@ -612,6 +612,7 @@ UINT rdpei_server_send_sc_ready_ex(RdpeiServerContext* context, UINT32 version,
{
ULONG written;
RdpeiServerPrivate* priv = context->priv;
UINT32 pduLen = 4;
if (priv->automataState != STATE_INITIAL)
{
@ -621,14 +622,17 @@ UINT rdpei_server_send_sc_ready_ex(RdpeiServerContext* context, UINT32 version,
Stream_SetPosition(priv->outputStream, 0);
if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4))
if (version >= RDPINPUT_PROTOCOL_V300)
pduLen += 4;
if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH + pduLen))
{
WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT16(priv->outputStream, EVENTID_SC_READY);
Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4);
Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH + pduLen);
Stream_Write_UINT32(priv->outputStream, version);
if (version >= RDPINPUT_PROTOCOL_V300)
Stream_Write_UINT32(priv->outputStream, features);

View File

@ -1,4 +1,4 @@
/**
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Graphics Pipeline Extension
*
@ -24,9 +24,12 @@
#endif
#include <winpr/crt.h>
#include <assert.h>
#include <winpr/stream.h>
#include <freerdp/channels/log.h>
#define WINPR_ASSERT(x) assert(x)
#define TAG CHANNELS_TAG("rdpgfx.common")
#include "rdpgfx_common.h"
@ -110,6 +113,9 @@ const char* rdpgfx_get_codec_id_string(UINT16 codecId)
*/
UINT rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header)
{
WINPR_ASSERT(s);
WINPR_ASSERT(header);
if (Stream_GetRemainingLength(s) < 8)
{
WLog_ERR(TAG, "calloc failed!");
@ -119,6 +125,13 @@ UINT rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header)
Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */
Stream_Read_UINT32(s, header->pduLength); /* pduLength (4 bytes) */
if ((header->pduLength < 8) || (Stream_GetRemainingLength(s) < (header->pduLength - 8)))
{
WLog_ERR(TAG, "header->pduLength %u less than 8!", header->pduLength);
return ERROR_INVALID_DATA;
}
return CHANNEL_RC_OK;
}

View File

@ -53,6 +53,12 @@
#include <freerdp/server/rdpgfx.h>
#include <freerdp/server/disp.h>
#if defined(CHANNEL_AINPUT_SERVER)
#include <freerdp/server/ainput.h>
#endif
extern void freerdp_channels_dummy(void);
void freerdp_channels_dummy(void)
{
audin_server_context* audin;
@ -91,6 +97,12 @@ void freerdp_channels_dummy(void)
rdpgfx_server_context_free(rdpgfx);
disp = disp_server_context_new(NULL);
disp_server_context_free(disp);
#if defined(CHANNEL_AINPUT_SERVER)
{
ainput_server_context* ainput = ainput_server_context_new(NULL);
ainput_server_context_free(ainput);
}
#endif
}
/**

View File

@ -615,7 +615,9 @@ static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
static INIT_ONCE g_Initialized = INIT_ONCE_STATIC_INIT;
static BOOL CALLBACK InitializeAvCodecs(PINIT_ONCE once, PVOID param, PVOID* context)
{
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
avcodec_register_all();
#endif
return TRUE;
}

View File

@ -1,7 +0,0 @@
message("PRELOADING android cache")
set(CMAKE_TOOLCHAIN_FILE "$ANDROID_NDK/build/cmake/android.toolchain.cmake" CACHE PATH "ToolChain file")
set(WITH_SANITIZE_ADDRESS ON)
set(FREERDP_EXTERNAL_SSL_PATH $ENV{ANDROID_SSL_PATH} CACHE PATH "android ssl")
# ANDROID_NDK and ANDROID_SDK must be set as environment variable
#set(ANDROID_NDK $ENV{ANDROID_SDK} CACHE PATH "Android NDK")
#set(ANDROID_SDK "${ANDROID_NDK}" CACHE PATH "android SDK")

View File

@ -1,11 +0,0 @@
message("PRELOADING cache")
set (WITH_MANPAGES OFF CACHE BOOL "man pages")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (WITH_CUPS OFF CACHE BOOL "CUPS printing")
set (WITH_GSSAPI ON CACHE BOOL "Kerberos support")
set (WITH_ALSA OFF CACHE BOOL "alsa audio")
set (WITH_FFMPEG OFF CACHE BOOL "ffmepg support")
set (WITH_XV OFF CACHE BOOL "xvideo support")
set (BUILD_TESTING ON CACHE BOOL "build testing")
set (WITH_XSHM OFF CACHE BOOL "build with xshm support")
set (WITH_SANITIZE_ADDRESS ON)

View File

@ -1,7 +0,0 @@
message("PRELOADING iOS cache")
set (CMAKE_TOOLCHAIN_FILE "cmake/iOSToolchain.cmake" CACHE PATH "ToolChain file")
set (FREERDP_IOS_EXTERNAL_SSL_PATH $ENV{FREERDP_IOS_EXTERNAL_SSL_PATH} CACHE PATH "android ssl")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (IOS_PLATFORM "SIMULATOR" CACHE STRING "iso platfrorm to build")
set (WITH_SANITIZE_ADDRESS ON CACHE BOOL "build with address sanitizer")
set (WITH_CLIENT OFF CACHE BOOL "disable iOS client")

View File

@ -1,53 +0,0 @@
message("PRELOADING cache")
set (BUILD_TESTING ON CACHE BOOL "testing")
set (WITH_MANPAGES OFF CACHE BOOL "man pages")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (BUILD_TESTING ON CACHE BOOL "build testing")
set (WITH_PULSE ON CACHE BOOL "pulse")
set (WITH_CHANNELS ON CACHE BOOL "channels")
set (BUILTIN_CHANNELS ON CACHE BOOL "static channels")
set (WITH_CUPS ON CACHE BOOL "cups")
set (WITH_WAYLAND ON CACHE BOOL "wayland")
set (WITH_GSSAPI ON CACHE BOOL "Kerberos support")
set (WITH_PCSC ON CACHE BOOL "PCSC")
set (WITH_JPEG ON CACHE BOOL "jpeg")
set (WITH_GSTREAMER_0_10 ON CACHE BOOL "gstreamer")
set (WITH_GSM ON CACHE BOOL "gsm")
set (CHANNEL_URBDRC ON CACHE BOOL "urbdrc")
set (CHANNEL_URBDRC_CLIENT ON CACHE BOOL "urbdrc client")
set (WITH_SERVER ON CACHE BOOL "server side")
set (WITH_DEBUG_ALL OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_CAPABILITIES OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_CERTIFICATE OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_CHANNELS OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_CLIPRDR OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_RDPGFX OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_DVC OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_KBD OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_LICENSE OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_NEGO OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_NLA OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_NTLM OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_RAIL OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_RDP OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_RDPEI OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_REDIR OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_RDPDR OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_RFX OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_SCARD OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_SND OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_SVC OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_THREADS OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_TIMEZONE OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_TRANSPORT OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_TSG OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_TSMF OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_WND OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_X11 OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_X11_CLIPRDR OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_X11_LOCAL_MOVESIZE OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_XV OFF CACHE BOOL "enable debug")
set (WITH_SAMPLE ON CACHE BOOL "samples")
set (WITH_NO_UNDEFINED ON CACHE BOOL "don't link with undefined symbols")
set (WITH_SANITIZE_ADDRESS ON)
set (WITH_PROXY_MODULES OFF CACHE BOOL "compile proxy modules")

View File

@ -1,8 +0,0 @@
message("PRELOADING mac cache")
set (WITH_MANPAGES OFF CACHE BOOL "man pages")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (WITH_CUPS ON CACHE BOOL "CUPS printing")
set (CHANNEL_URBDRC OFF CACHE BOOL "USB redirection")
set (WITH_X11 ON CACHE BOOL "Enable X11")
set (BUILD_TESTING ON CACHE BOOL "build testing")
set (WITH_SANITIZE_ADDRESS ON)

View File

@ -1,11 +0,0 @@
message("PRELOADING cache")
set (WITH_MANPAGES OFF CACHE BOOL "man pages")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (WITH_CUPS OFF CACHE BOOL "CUPS printing")
set (WITH_GSSAPI ON CACHE BOOL "Kerberos support")
set (WITH_ALSA OFF CACHE BOOL "alsa audio")
set (WITH_FFMPEG OFF CACHE BOOL "ffmepg support")
set (WITH_XV OFF CACHE BOOL "xvideo support")
set (BUILD_TESTING ON CACHE BOOL "build testing")
set (WITH_XSHM OFF CACHE BOOL "build with xshm support")
set (WITH_SANITIZE_ADDRESS ON)

View File

@ -1,6 +0,0 @@
message("PRELOADING windows cache")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (WITH_SERVER "ON" CACHE BOOL "Build server binaries")
set (CHANNEL_URBDRC OFF CACHE BOOL "USB redirection")
set (BUILD_TESTING ON CACHE BOOL "build testing")
set (WITH_SANITIZE_ADDRESS ON)

View File

@ -43,7 +43,10 @@ if(FREERDP_VENDOR AND WITH_CLIENT)
add_subdirectory(iOS)
endif()
else()
add_subdirectory(Mac)
option(WITH_CLIENT_MAC "Build native mac client" ON)
if (WITH_CLIENT_MAC)
add_subdirectory(Mac)
endif()
endif()
endif()

View File

@ -27,6 +27,7 @@
#endif
#include <assert.h>
#include <winpr/sspicli.h>
#include <float.h>
#include <X11/Xlib.h>
@ -1183,20 +1184,12 @@ static BOOL xf_pre_connect(freerdp* instance)
if (!settings->Username && !settings->CredentialsFromStdin && !settings->SmartcardLogon)
{
int rc;
char login_name[MAX_PATH] = { 0 };
ULONG size = sizeof(login_name) - 1;
#ifdef HAVE_GETLOGIN_R
rc = getlogin_r(login_name, sizeof(login_name));
#else
strncpy(login_name, getlogin(), sizeof(login_name));
rc = 0;
#endif
if (rc == 0)
if (GetUserNameExA(NameSamCompatible, login_name, &size))
{
settings->Username = _strdup(login_name);
if (!settings->Username)
if (!freerdp_settings_set_string(settings, FreeRDP_Username, login_name))
return FALSE;
WLog_INFO(TAG, "No user name set. - Using login name: %s", settings->Username);

View File

@ -1,33 +0,0 @@
if (X264_INCLUDE_DIR AND X264_LIBRARY)
set(X264_FIND_QUIETLY TRUE)
endif (X264_INCLUDE_DIR AND X264_LIBRARY)
find_path(X264_INCLUDE_DIR NAMES x264.h
PATH_SUFFIXES include
HINTS ${X264_ROOT})
find_library(X264_LIBRARY
NAMES x264
PATH_SUFFIXES lib
HINTS ${X264_ROOT})
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(x264 DEFAULT_MSG X264_LIBRARY X264_INCLUDE_DIR)
if (X264_INCLUDE_DIR AND X264_LIBRARY)
set(X264_FOUND TRUE)
set(X264_LIBRARIES ${X264_LIBRARY})
endif (X264_INCLUDE_DIR AND X264_LIBRARY)
if (X264_FOUND)
if (NOT X264_FIND_QUIETLY)
message(STATUS "Found x264: ${X264_LIBRARIES}")
endif (NOT X264_FIND_QUIETLY)
else (X264_FOUND)
if (X264_FIND_REQUIRED)
message(FATAL_ERROR "x264 was not found")
endif(X264_FIND_REQUIRED)
endif (X264_FOUND)
mark_as_advanced(X264_INCLUDE_DIR X264_LIBRARY)

View File

@ -1,196 +0,0 @@
# This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake
# files which are included with CMake 2.8.4
# It has been altered for iOS development
# Options:
#
# IOS_PLATFORM = OS (default) or SIMULATOR
# This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders
# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch.
# SIMULATOR - used to build for the Simulator platforms, which have an x86 arch.
#
# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder
# By default this location is automatcially chosen based on the IOS_PLATFORM value above.
# If set manually, it will override the default location and force the user of a particular Developer Platform
#
# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder
# By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value.
# In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path.
# If set manually, this will force the use of a specific SDK version
# Macros:
#
# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE)
# A convenience macro for setting xcode specific properties on targets
# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1")
#
# find_host_package (PROGRAM ARGS)
# A macro used to find executable programs on the host system, not within the iOS environment.
# Thanks to the android-cmake project for providing the command
# Standard settings
set (CMAKE_SYSTEM_NAME Darwin)
set (CMAKE_SYSTEM_VERSION 1)
set (UNIX True)
set (APPLE True)
set (IOS True)
# Required as of cmake 2.8.10
#set (CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE)
# Determine the cmake host system version so we know where to find the iOS SDKs
find_program (CMAKE_UNAME uname /bin /usr/bin /usr/local/bin)
if (CMAKE_UNAME)
exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION)
string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}")
endif (CMAKE_UNAME)
# Force the compilers to gcc for iOS
include (CMakeForceCompiler)
CMAKE_FORCE_C_COMPILER (/usr/bin/clang Apple)
CMAKE_FORCE_CXX_COMPILER (/usr/bin/clang++ Apple)
set(CMAKE_AR ar CACHE FILEPATH "" FORCE)
# Skip the platform compiler checks for cross compiling
#set (CMAKE_CXX_COMPILER_WORKS TRUE)
#set (CMAKE_C_COMPILER_WORKS TRUE)
# All iOS/Darwin specific settings - some may be redundant
set (CMAKE_SHARED_LIBRARY_PREFIX "lib")
set (CMAKE_SHARED_LIBRARY_SUFFIX ".dylib")
set (CMAKE_SHARED_MODULE_PREFIX "lib")
set (CMAKE_SHARED_MODULE_SUFFIX ".so")
set (CMAKE_MODULE_EXISTS 1)
set (CMAKE_DL_LIBS "")
set (CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ")
set (CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ")
set (CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}")
set (CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}")
# Hidden visibilty is required for cxx on iOS
set (CMAKE_C_FLAGS_INIT "")
set (CMAKE_CXX_FLAGS_INIT "-fvisibility=hidden -fvisibility-inlines-hidden -isysroot ${CMAKE_OSX_SYSROOT}")
set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}")
set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}")
set (CMAKE_PLATFORM_HAS_INSTALLNAME 1)
set (CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names")
set (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names")
set (CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,")
set (CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,")
set (CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a")
# hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree
# (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache
# and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun)
# hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex
if (NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool)
endif (NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
# Setup iOS platform unless specified manually with IOS_PLATFORM
if (NOT DEFINED IOS_PLATFORM)
set (IOS_PLATFORM "OS")
endif (NOT DEFINED IOS_PLATFORM)
set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform")
# Check the platform selection and setup for developer root
if (${IOS_PLATFORM} STREQUAL "OS")
set (IOS_PLATFORM_LOCATION "iPhoneOS.platform")
# This causes the installers to properly locate the output libraries
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos")
elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR")
set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform")
# This causes the installers to properly locate the output libraries
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator")
else (${IOS_PLATFORM} STREQUAL "OS")
message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or SIMULATOR")
endif (${IOS_PLATFORM} STREQUAL "OS")
# Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT
# Note Xcode 4.3 changed the installation location, choose the most recent one available
set (XCODE_POST_43_ROOT "/Applications/Xcode.app/Contents/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
set (XCODE_PRE_43_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
if (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
if (EXISTS ${XCODE_POST_43_ROOT})
set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_POST_43_ROOT})
elseif(EXISTS ${XCODE_PRE_43_ROOT})
set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_PRE_43_ROOT})
endif (EXISTS ${XCODE_POST_43_ROOT})
endif (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
set (CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform")
# Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT
if (NOT DEFINED CMAKE_IOS_SDK_ROOT)
file (GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*")
if (_CMAKE_IOS_SDKS)
list (SORT _CMAKE_IOS_SDKS)
list (REVERSE _CMAKE_IOS_SDKS)
list (GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT)
else (_CMAKE_IOS_SDKS)
message (FATAL_ERROR "No iOS SDK's found in default search path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.")
endif (_CMAKE_IOS_SDKS)
message (STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}")
endif (NOT DEFINED CMAKE_IOS_SDK_ROOT)
set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK")
# Set the sysroot default to the most recent SDK
set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support")
# set the architecture for iOS
# NOTE: Currently both ARCHS_STANDARD_32_BIT and ARCHS_UNIVERSAL_IPHONE_OS set armv7 only, so set both manually
if (${IOS_PLATFORM} STREQUAL "OS")
set (IOS_ARCH armv7 armv7s)
set (CMAKE_SYSTEM_PROCESSOR armv7)
else (${IOS_PLATFORM} STREQUAL "OS")
set (IOS_ARCH i386)
set (CMAKE_SYSTEM_PROCESSOR i386)
endif (${IOS_PLATFORM} STREQUAL "OS")
set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string "Build architecture for iOS")
# Set the find root to the iOS developer roots and to user defined paths
set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE string "iOS find search path root")
# default to searching for frameworks first
set (CMAKE_FIND_FRAMEWORK FIRST)
# set up the default search directories for frameworks
set (CMAKE_SYSTEM_FRAMEWORK_PATH
${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks
${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks
${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks
)
# only search the iOS sdks, not the remainder of the host filesystem
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# This little macro lets you set any XCode specific property
macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
endmacro (set_xcode_property)
# This macro lets you find executable programs on the host system
macro (find_host_package)
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
set (IOS FALSE)
find_package(${ARGN})
set (IOS TRUE)
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endmacro (find_host_package)

View File

@ -25,6 +25,7 @@
#cmakedefine HAVE_VALGRIND_MEMCHECK_H
#cmakedefine HAVE_EXECINFO_H
#cmakedefine HAVE_GETLOGIN_R
#cmakedefine HAVE_GETPWUID_R
/* Features */
#cmakedefine SWRESAMPLE_FOUND
@ -63,9 +64,9 @@
#cmakedefine WITH_FFMPEG
#cmakedefine WITH_DSP_EXPERIMENTAL
#cmakedefine WITH_DSP_FFMPEG
#cmakedefine WITH_X264
#cmakedefine WITH_OPENCL
#cmakedefine WITH_MEDIA_FOUNDATION
#cmakedefine WITH_MEDIACODEC
#cmakedefine WITH_VAAPI
@ -74,6 +75,9 @@
#cmakedefine WITH_RDPDR
/* Channels */
#cmakedefine CHANNEL_AINPUT
#cmakedefine CHANNEL_AINPUT_CLIENT
#cmakedefine CHANNEL_AINPUT_SERVER
#cmakedefine CHANNEL_AUDIN
#cmakedefine CHANNEL_AUDIN_CLIENT
#cmakedefine CHANNEL_AUDIN_SERVER

View File

@ -1,86 +0,0 @@
Overview
========
The FreeRDP Android port consists of three parts:
* Android Java GUI (client/Android/Studio)
* FreeRDP library and its dependencies
* JNI bindings (client/Android/android_freerdp.c
and client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java)
Build requirements
=================
For the Android port some additional dependencies need to be fulfilled:
* for JNI
- CMake >= 3.0
- Android NDK (>= r9)
* for the Java GUI
- Android SDK
FreeRDP requires openssl libraries for building but they are not part of the
Android NDK and therefore they need to be prebuild manually.
For jpeg support https://github.com/akallabeth/jpeg8d has been tested and used.
However, any other static builds should work as well.
Build native libraries:
======================
From the project root run the build script
./scripts/android-build-freerdp.sh --ndk <ANDROID_NDK> --sdk <ANDROID_SDK>
Set ANDROID_NDK and ANDROID_SDK to the absolute paths on your machine.
This will fetch sources from git and build OpenSSL, OpenH264, libJPEG.
The native FreeRDP libraries will also be build.
Currently the default script builds for:
* armeabi
* armeabi-v7a
* x86
* mips
* arm64-v8a
* x86_64
* mips64
When the script is finished the libraries are ready for android studio to
be picked up in client/Android/Studio/freeRDPCore/src/main/jniLibs
The default configuration build configuration can be found in
./scripts/android-build.conf and is configured to provide debug builds.
They are limited to API level 21 and above.
If release binaries (and old android API support) are required, build 32 bit architectures with
./scripts/android-build-freerdp.sh --ndk <ANDROID_NDK> --sdk <ANDROID_SDK> --conf ./scripts/android-build-32.conf
and 64 bit architectures with
./scripts/android-build-freerdp.sh --ndk <ANDROID_NDK> --sdk <ANDROID_SDK> --conf ./scripts/android-build-64.conf
Building the APK (Android Studio)
================
* Import the folder client/Android/Studio in Android Studio
* You are ready to go
Building the APK (gradle)
================
* change to directory client/Android/Studio
* run ./gradlew build to build
* run ./gradlew tasks for other gradle options
Development
===========
Updating JNI
------------
Whenever the FreeRDP API changes or you need some extra functionality in your Java
GUI the JNI needs to be updated.
The JNI functions are defined in client/Android/android_freerdp.c
Add the new functions to the methods struct.
* edit client/Android/src/com/freerdp/afreerdp/services/LibFreeRDP.Java to
reflect your changes
* edit client/Android/android_freerdp.c and adjust the methods struct to reflect
the changes made.

View File

@ -1,100 +0,0 @@
Overview
========
The FreeRDP iOS port allows users to enjoy FreeRDP features on Apple iOS devices.
The application was written to be compatible with devices running iOS 4.3 or higher.
Build requirements
==================
The following prerequisites are required in order to build the iOS port:
- cmake version >= 2.8.9
- latest Xcode installed (>= 4.6)
- installed Provisioning Profile and iOS Developer Certificate for code signing
(not required for simulator builds)
- pre-build static OpenSSL libraries (see below)
FreeRDP requires OpenSSL libraries for building but they are not part of the iOS SDK and therefore they need to be pre-build manually.
There are various versions and builds of static OpenSSL libraries floating around like iOSPorts.
At the time of writing we have tested and used a small script (OpenSSL-DownloadAndBuild.command) that downloads and builds armv7, armv7s and i386 versions of the OpenSSL 1.0.0e libraries.
If you don't care about modifying the OpenSSL build you can run the following command in the FreeRDP root directory:
./scripts/OpenSSL-DownloadAndBuild.command
The output of the script will be found in external/openssl/. In case you want a
different install/build directory you specify it as first parameter:
./scripts/OpenSSL-DownloadAndBuild.command /tmp/
In the example above the output can then be found in /tmp/openssl.
The script uses oldest iOS/iPhoneSimulator SDK found on the build machine per default. If it is required to build against a specific SDK version
the variable SDK_VERSION can be used to specify it. The minimum SDK version that should be used can be set with MIN_SDK_VERSION within the script.
When the script is finished you will find libcrypto.a and libssl.at, both universal libraries containing all openssl/lib
subfolder in the specified
install directory (external per default)
When the script finishes you will find libcrypto.a and libssl.a, both universal
binary libraries containing arm and i386 targets in order to compile FreeRDP for
iOS devices and the simulator, in the lib subfolder of your installation
directory.
If you build OpenSSL youself or with an install directory specified you need to set FREERDP_IOS_EXTERNAL_SSL_PATH when running cmake.
Building
========
Run the following commands in the top level FreeRDP directory:
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/iOSToolchain.cmake -GXcode
This command will create a XCode project in the FreeRDP root folder called FreeRDP.xcodeproj.
Open the project in XCode and modify, build or run the app.
Alternatively you can also build the project from the command line using xcodebuild:
xcodebuild -project FreeRDP.xcodeproj -configuration Debug -sdk iphoneos6.1
or with cmake --build . in your build directory.
Notes:
* XCode, by default will build the application into its derived data location (usually in ~/Library/Developer/...).
If you want to specify an output directory add CONFIGURATION_BUILD_DIR=<output-path-here> to the end of above command line.
* If using XCode choose "Open Other" from the welcome screen, browse to the FreeRDP root directory and select FreeRDP.xcodeproj. Alternatively you can
also start it with "open FreeRDP.xcodeproj".
* If you switch between platforms (OS and SIMULATOR) please remove CMakeCache.txt and CMakeFiles/ before calling cmake again.
Otherwise build errors might occur (this seems to be a bug with cmake or the cmake scripts). To switch between platforms do:
rm CMakeCache.txt
rm -rf CMakeFiles/
before you run a new cmake command with the desired platform.
cmake variables
===============
CMAKE_TOOLCHAIN_FILE
* the toolchain file to use must be cmake/iOSToolchain.cmake
IOS_PLATFORM (OS (default), SIMULATOR)
* the platform for which to build iFreeRDP. OS compiles for iOS devices (using armv7 and armv7s ABIs) and SIMULATOR compiles for the iOS Simulator (i386)
CMAKE_IOS_DEVELOPER_ROOT (used by toolchain file)
* absolute path to the iOS developer platform (i.e. /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer) the toolchain file will usually auto-detect the correct Developer platform depending on IOS_PLATFORM
CMAKE_IOS_SDK_ROOT (used by toolchain file)
* absolute path to the iOS SDK (i.e. /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk) the toolchain file will usually auto-detect the correct SDK, depending on IOS_PLATFORM
FREERDP_IOS_EXTERNAL_SSL_PATH (used by FindOpenSSL)
* absolut root path to the pre-built static OpenSSL libraries
CODE_SIGN_IDENTITY
* specify the identity to sign the code with

View File

@ -1,7 +0,0 @@
Starting with "El Capitan" Apple removed the openssl headers. Therefore it's
required to build openssl manually upfront. For example by using MacPorts or Homebrew.
To build FreeRDP against this library it's required to set the PKG_CONFIG_PATH
pointing to the openssl root directory befor building.
For example with brew it would look like this:
export PKG_CONFIG_PATH=$(brew --prefix)/opt/openssl/lib/pkgconfig

View File

@ -0,0 +1,61 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Audio Input Redirection Virtual Channel
*
* Copyright 2022 Armin Novak <anovak@thincast.com>
* Copyright 2022 Thincast Technologies GmbH
*
* 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_AINPUT_H
#define FREERDP_CHANNEL_AINPUT_H
#include <freerdp/api.h>
#include <freerdp/dvc.h>
#include <freerdp/types.h>
#define AINPUT_CHANNEL_NAME "ainput"
#define AINPUT_DVC_CHANNEL_NAME "FreeRDP::Advanced::Input"
typedef enum
{
MSG_AINPUT_VERSION = 0x01,
MSG_AINPUT_MOUSE = 0x02
} eAInputMsgType;
typedef enum
{
AINPUT_FLAGS_WHEEL = 0x0001,
AINPUT_FLAGS_MOVE = 0x0004,
AINPUT_FLAGS_DOWN = 0x0008,
AINPUT_FLAGS_REL = 0x0010,
AINPUT_FLAGS_HAVE_REL = 0x0020,
/* Pointer Flags */
AINPUT_FLAGS_BUTTON1 = 0x1000, /* left */
AINPUT_FLAGS_BUTTON2 = 0x2000, /* right */
AINPUT_FLAGS_BUTTON3 = 0x4000, /* middle */
/* Extended Pointer Flags */
AINPUT_XFLAGS_BUTTON1 = 0x0100,
AINPUT_XFLAGS_BUTTON2 = 0x0200
} AInputEventFlags;
typedef struct ainput_client_context AInputClientContext;
#define AINPUT_VERSION_MAJOR 1
#define AINPUT_VERSION_MINOR 0
#endif /* FREERDP_CHANNEL_AINPUT_H */

View File

@ -0,0 +1,38 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Display Update Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.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_AINPUT_CLIENT_AINPUT_H
#define FREERDP_CHANNEL_AINPUT_CLIENT_AINPUT_H
#include <freerdp/channels/ainput.h>
typedef UINT (*pcAInputSendInputEvent)(AInputClientContext* context, UINT64 flags, INT32 x,
INT32 y);
struct ainput_client_context
{
void* handle;
void* custom;
pcAInputSendInputEvent AInputSendInputEvent;
};
#endif /* FREERDP_CHANNEL_AINPUT_CLIENT_AINPUT_H */

View File

@ -0,0 +1,114 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* AInput Virtual Channel Extension
*
* Copyright 2022 Armin Novak <anovak@thincast.com>
* Copyright 2022 Thincast Technologies GmbH
*
* 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_AINPUT_SERVER_H
#define FREERDP_CHANNEL_AINPUT_SERVER_H
#include <freerdp/channels/wtsvc.h>
typedef enum AINPUT_SERVER_OPEN_RESULT
{
AINPUT_SERVER_OPEN_RESULT_OK = 0,
AINPUT_SERVER_OPEN_RESULT_CLOSED = 1,
AINPUT_SERVER_OPEN_RESULT_NOTSUPPORTED = 2,
AINPUT_SERVER_OPEN_RESULT_ERROR = 3
} AINPUT_SERVER_OPEN_RESULT;
typedef struct _ainput_server_context ainput_server_context;
typedef UINT (*psAInputServerInitialize)(ainput_server_context* context, BOOL externalThread);
typedef UINT (*psAInputServerPoll)(ainput_server_context* context);
typedef BOOL (*psAInputServerChannelHandle)(ainput_server_context* context, HANDLE* handle);
typedef UINT (*psAInputServerOpen)(ainput_server_context* context);
typedef UINT (*psAInputServerClose)(ainput_server_context* context);
typedef BOOL (*psAInputServerIsOpen)(ainput_server_context* context);
typedef UINT (*psAInputServerOpenResult)(ainput_server_context* context,
AINPUT_SERVER_OPEN_RESULT result);
typedef UINT (*psAInputServerMouseEvent)(ainput_server_context* context, UINT64 timestamp,
UINT64 flags, INT32 x, INT32 y);
struct _ainput_server_context
{
HANDLE vcm;
/* Server self-defined pointer. */
void* data;
/*** APIs called by the server. ***/
/**
* Open the ainput channel.
*/
psAInputServerOpen Open;
/**
* Optional: Set thread handling.
* When externalThread=TRUE the application is responsible to call
* ainput_server_context_poll periodically to process input events.
*
* Defaults to externalThread=FALSE
*/
psAInputServerInitialize Initialize;
/**
* @brief Poll When externalThread=TRUE call periodically from your main loop.
* if externalThread=FALSE do not call.
*/
psAInputServerPoll Poll;
/**
* @brief Poll When externalThread=TRUE call to get a handle to wait for events.
* Will return FALSE until the handle is available.
*/
psAInputServerChannelHandle ChannelHandle;
/**
* Close the ainput channel.
*/
psAInputServerClose Close;
/**
* Status of the ainput channel.
*/
psAInputServerIsOpen IsOpen;
/*** Callbacks registered by the server. ***/
/**
* Receive ainput mouse event PDU.
*/
psAInputServerMouseEvent MouseEvent;
rdpContext* rdpcontext;
};
#ifdef __cplusplus
extern "C"
{
#endif
FREERDP_API ainput_server_context* ainput_server_context_new(HANDLE vcm);
FREERDP_API void ainput_server_context_free(ainput_server_context* context);
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_CHANNEL_AINPUT_SERVER_H */

View File

@ -220,12 +220,6 @@ if(WITH_JPEG)
freerdp_library_add(${JPEG_LIBRARIES})
endif()
if(WITH_X264)
set(CODEC_SRCS ${CODEC_SRCS} codec/h264_x264.c)
freerdp_include_directory_add(${X264_INCLUDE_DIR})
freerdp_library_add(${X264_LIBRARIES})
endif()
if(WITH_OPENH264)
set(CODEC_SRCS ${CODEC_SRCS} codec/h264_openh264.c)
freerdp_include_directory_add(${OPENH264_INCLUDE_DIR})
@ -244,6 +238,10 @@ if(WIN32 AND WITH_MEDIA_FOUNDATION)
set(CODEC_SRCS ${CODEC_SRCS} codec/h264_mf.c)
endif()
if(ANDROID AND WITH_MEDIACODEC)
list(APPEND CODEC_SRCS codec/h264_mediacodec.c)
endif()
freerdp_module_add(${CODEC_SRCS})
if(BUILD_TESTING)

View File

@ -571,7 +571,9 @@ BOOL freerdp_dsp_ffmpeg_supports_format(const AUDIO_FORMAT* format, BOOL encode)
FREERDP_DSP_CONTEXT* freerdp_dsp_ffmpeg_context_new(BOOL encode)
{
FREERDP_DSP_CONTEXT* context;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
avcodec_register_all();
#endif
context = calloc(1, sizeof(FREERDP_DSP_CONTEXT));
if (!context)
@ -667,7 +669,9 @@ BOOL freerdp_dsp_ffmpeg_decode(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT*
if (!context || !srcFormat || !data || !out || context->encoder)
return FALSE;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
av_init_packet(context->packet);
#endif
context->packet->data = (uint8_t*)data;
context->packet->size = length;
return ffmpeg_decode(context->context, context->packet, context->frame, context->rcontext,

View File

@ -484,7 +484,7 @@ INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op, RECTANGLE_16* regionRects,
#define MAX_SUBSYSTEMS 10
static INIT_ONCE subsystems_once = INIT_ONCE_STATIC_INIT;
static H264_CONTEXT_SUBSYSTEM* subSystems[MAX_SUBSYSTEMS];
static H264_CONTEXT_SUBSYSTEM* subSystems[MAX_SUBSYSTEMS] = { 0 };
#if defined(_WIN32) && defined(WITH_MEDIA_FOUNDATION)
extern H264_CONTEXT_SUBSYSTEM g_Subsystem_MF;
@ -493,7 +493,14 @@ extern H264_CONTEXT_SUBSYSTEM g_Subsystem_MF;
static BOOL CALLBACK h264_register_subsystems(PINIT_ONCE once, PVOID param, PVOID* context)
{
int i = 0;
ZeroMemory(subSystems, sizeof(subSystems));
#ifdef WITH_MEDIACODEC
{
extern H264_CONTEXT_SUBSYSTEM g_Subsystem_mediacodec;
subSystems[i] = &g_Subsystem_mediacodec;
i++;
}
#endif
#if defined(_WIN32) && defined(WITH_MEDIA_FOUNDATION)
{
subSystems[i] = &g_Subsystem_MF;
@ -513,13 +520,6 @@ static BOOL CALLBACK h264_register_subsystems(PINIT_ONCE once, PVOID param, PVOI
subSystems[i] = &g_Subsystem_libavcodec;
i++;
}
#endif
#ifdef WITH_X264
{
extern H264_CONTEXT_SUBSYSTEM g_Subsystem_x264;
subSystems[i] = &g_Subsystem_x264;
i++;
}
#endif
return i > 0;
}

View File

@ -0,0 +1,649 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* H.264 Bitmap Compression
*
* Copyright 2022 Ely Ronnen <elyronnen@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/wlog.h>
#include <assert.h>
#include <winpr/library.h>
#include <freerdp/log.h>
#include <freerdp/codec/h264.h>
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaFormat.h>
#include "h264.h"
#define WINPR_ASSERT(x) assert(x)
#define RESOLVE_MEDIANDK_FUNC(sys, name) \
({ \
BOOL rc = TRUE; \
sys->fn##name = GetProcAddress(sys->mediandkLibrary, #name); \
if (sys->fn##name == NULL) \
{ \
WLog_Print(h264->log, WLOG_ERROR, \
"Error resolving function " #name " from libmediandk.so"); \
rc = FALSE; \
} \
rc; \
})
#define RESOLVE_MEDIANDK_VARIABLE(sys, member, exported) \
({ \
BOOL rc = FALSE; \
const char** temp = GetProcAddress(sys->mediandkLibrary, exported); \
if (temp == NULL) \
{ \
WLog_Print(h264->log, WLOG_ERROR, \
"Error resolving variable " exported " from libmediandk.so"); \
} \
else \
{ \
sys->member = *temp; \
rc = TRUE; \
} \
rc; \
})
typedef AMediaFormat* (*AMediaFormat_new_t)(void);
typedef media_status_t (*AMediaFormat_delete_t)(AMediaFormat*);
typedef const char* (*AMediaFormat_toString_t)(AMediaFormat*);
typedef void (*AMediaFormat_setInt32_t)(AMediaFormat*, const char*, int32_t);
typedef void (*AMediaFormat_setString_t)(AMediaFormat*, const char*, const char*);
typedef AMediaCodec* (*AMediaCodec_createDecoderByType_t)(const char*);
typedef media_status_t (*AMediaCodec_delete_t)(AMediaCodec*);
typedef media_status_t (*AMediaCodec_configure_t)(AMediaCodec*, const AMediaFormat*, ANativeWindow*,
AMediaCrypto*, uint32_t);
typedef media_status_t (*AMediaCodec_start_t)(AMediaCodec*);
typedef media_status_t (*AMediaCodec_stop_t)(AMediaCodec*);
typedef uint8_t* (*AMediaCodec_getInputBuffer_t)(AMediaCodec*, size_t, size_t*);
typedef uint8_t* (*AMediaCodec_getOutputBuffer_t)(AMediaCodec*, size_t, size_t*);
typedef ssize_t (*AMediaCodec_dequeueInputBuffer_t)(AMediaCodec*, int64_t);
typedef media_status_t (*AMediaCodec_queueInputBuffer_t)(AMediaCodec*, size_t, ssize_t, size_t,
uint64_t, uint32_t);
typedef ssize_t (*AMediaCodec_dequeueOutputBuffer_t)(AMediaCodec*, AMediaCodecBufferInfo*, int64_t);
typedef AMediaFormat* (*AMediaCodec_getOutputFormat_t)(AMediaCodec*);
typedef media_status_t (*AMediaCodec_releaseOutputBuffer_t)(AMediaCodec*, size_t, bool);
typedef media_status_t (*AMediaCodec_setParameters_t)(AMediaCodec*, const AMediaFormat*); // 26
typedef media_status_t (*AMediaCodec_getName_t)(AMediaCodec*, char**); // 28
typedef void (*AMediaCodec_releaseName_t)(AMediaCodec*, char*); // 28
typedef AMediaFormat* (*AMediaCodec_getInputFormat_t)(AMediaCodec*); // 28
const int COLOR_FormatYUV420Planar = 19;
const int COLOR_FormatYUV420Flexible = 0x7f420888;
struct _H264_CONTEXT_MEDIACODEC
{
AMediaCodec* decoder;
AMediaFormat* inputFormat;
AMediaFormat* outputFormat;
int32_t width;
int32_t height;
ssize_t currentOutputBufferIndex;
// libmediandk.so imports
HMODULE mediandkLibrary;
AMediaFormat_new_t fnAMediaFormat_new;
AMediaFormat_delete_t fnAMediaFormat_delete;
AMediaFormat_toString_t fnAMediaFormat_toString;
AMediaFormat_setInt32_t fnAMediaFormat_setInt32;
AMediaFormat_setString_t fnAMediaFormat_setString;
AMediaCodec_createDecoderByType_t fnAMediaCodec_createDecoderByType;
AMediaCodec_delete_t fnAMediaCodec_delete;
AMediaCodec_configure_t fnAMediaCodec_configure;
AMediaCodec_start_t fnAMediaCodec_start;
AMediaCodec_stop_t fnAMediaCodec_stop;
AMediaCodec_getInputBuffer_t fnAMediaCodec_getInputBuffer;
AMediaCodec_getOutputBuffer_t fnAMediaCodec_getOutputBuffer;
AMediaCodec_dequeueInputBuffer_t fnAMediaCodec_dequeueInputBuffer;
AMediaCodec_queueInputBuffer_t fnAMediaCodec_queueInputBuffer;
AMediaCodec_dequeueOutputBuffer_t fnAMediaCodec_dequeueOutputBuffer;
AMediaCodec_getOutputFormat_t fnAMediaCodec_getOutputFormat;
AMediaCodec_releaseOutputBuffer_t fnAMediaCodec_releaseOutputBuffer;
AMediaCodec_setParameters_t fnAMediaCodec_setParameters;
AMediaCodec_getName_t fnAMediaCodec_getName;
AMediaCodec_releaseName_t fnAMediaCodec_releaseName;
AMediaCodec_getInputFormat_t fnAMediaCodec_getInputFormat;
const char* gAMediaFormatKeyMime;
const char* gAMediaFormatKeyWidth;
const char* gAMediaFormatKeyHeight;
const char* gAMediaFormatKeyColorFormat;
};
typedef struct _H264_CONTEXT_MEDIACODEC H264_CONTEXT_MEDIACODEC;
static int load_libmediandk(H264_CONTEXT* h264)
{
BOOL rc;
H264_CONTEXT_MEDIACODEC* sys;
WINPR_ASSERT(h264);
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
WINPR_ASSERT(sys);
WLog_Print(h264->log, WLOG_DEBUG, "MediaCodec Loading libmediandk.so");
sys->mediandkLibrary = LoadLibraryA("libmediandk.so");
if (sys->mediandkLibrary == NULL)
{
WLog_Print(h264->log, WLOG_WARN, "Error loading libmediandk.so");
return -1;
}
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaFormat_new);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaFormat_delete);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaFormat_toString);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaFormat_setInt32);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaFormat_setString);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_createDecoderByType);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_delete);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_configure);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_start);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_stop);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_getInputBuffer);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_getOutputBuffer);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_dequeueInputBuffer);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_queueInputBuffer);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_dequeueOutputBuffer);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_getOutputFormat);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_releaseOutputBuffer);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_setParameters);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_getName);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_releaseName);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_FUNC(sys, AMediaCodec_getInputFormat);
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_VARIABLE(sys, gAMediaFormatKeyMime, "AMEDIAFORMAT_KEY_MIME");
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_VARIABLE(sys, gAMediaFormatKeyWidth, "AMEDIAFORMAT_KEY_WIDTH");
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_VARIABLE(sys, gAMediaFormatKeyHeight, "AMEDIAFORMAT_KEY_HEIGHT");
if (!rc)
return -1;
rc = RESOLVE_MEDIANDK_VARIABLE(sys, gAMediaFormatKeyColorFormat,
"AMEDIAFORMAT_KEY_COLOR_FORMAT");
if (!rc)
return -1;
return 0;
}
static void unload_libmediandk(H264_CONTEXT* h264)
{
H264_CONTEXT_MEDIACODEC* sys;
WINPR_ASSERT(h264);
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
WINPR_ASSERT(sys);
if (NULL == sys->mediandkLibrary)
{
return;
}
FreeLibrary(sys->mediandkLibrary);
}
static void set_mediacodec_format(H264_CONTEXT* h264, AMediaFormat** formatVariable,
AMediaFormat* newFormat)
{
media_status_t status = AMEDIA_OK;
H264_CONTEXT_MEDIACODEC* sys;
WINPR_ASSERT(h264);
WINPR_ASSERT(formatVariable);
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
WINPR_ASSERT(sys);
if (*formatVariable != NULL)
{
status = sys->fnAMediaFormat_delete(*formatVariable);
if (status != AMEDIA_OK)
{
WLog_Print(h264->log, WLOG_ERROR, "Error AMediaFormat_delete %d", status);
}
}
*formatVariable = newFormat;
}
static void release_current_outputbuffer(H264_CONTEXT* h264)
{
media_status_t status = AMEDIA_OK;
H264_CONTEXT_MEDIACODEC* sys;
WINPR_ASSERT(h264);
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
WINPR_ASSERT(sys);
if (sys->currentOutputBufferIndex < 0)
{
return;
}
status =
sys->fnAMediaCodec_releaseOutputBuffer(sys->decoder, sys->currentOutputBufferIndex, FALSE);
if (status != AMEDIA_OK)
{
WLog_Print(h264->log, WLOG_ERROR, "Error AMediaCodec_releaseOutputBuffer %d", status);
}
sys->currentOutputBufferIndex = -1;
}
static int mediacodec_compress(H264_CONTEXT* h264, const BYTE** pSrcYuv, const UINT32* pStride,
BYTE** ppDstData, UINT32* pDstSize)
{
WINPR_ASSERT(h264);
WINPR_ASSERT(pSrcYuv);
WINPR_ASSERT(pStride);
WINPR_ASSERT(ppDstData);
WINPR_ASSERT(pDstSize);
WLog_Print(h264->log, WLOG_ERROR, "MediaCodec is not supported as an encoder");
return -1;
}
static int mediacodec_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize)
{
ssize_t inputBufferId = -1;
size_t inputBufferSize, outputBufferSize;
uint8_t* inputBuffer;
media_status_t status;
const char* media_format;
BYTE** pYUVData;
UINT32* iStride;
H264_CONTEXT_MEDIACODEC* sys;
WINPR_ASSERT(h264);
WINPR_ASSERT(pSrcData);
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
WINPR_ASSERT(sys);
pYUVData = h264->pYUVData;
WINPR_ASSERT(pYUVData);
iStride = h264->iStride;
WINPR_ASSERT(iStride);
release_current_outputbuffer(h264);
if (sys->width == 0)
{
int32_t width = h264->width;
int32_t height = h264->height;
if (width % 16 != 0)
width += 16 - width % 16;
if (height % 16 != 0)
height += 16 - height % 16;
WLog_Print(h264->log, WLOG_DEBUG, "MediaCodec setting width and height [%d,%d]", width,
height);
sys->fnAMediaFormat_setInt32(sys->inputFormat, sys->gAMediaFormatKeyWidth, width);
sys->fnAMediaFormat_setInt32(sys->inputFormat, sys->gAMediaFormatKeyHeight, height);
status = sys->fnAMediaCodec_setParameters(sys->decoder, sys->inputFormat);
if (status != AMEDIA_OK)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_setParameters failed: %d", status);
return -1;
}
sys->width = width;
sys->height = height;
}
while (true)
{
UINT32 inputBufferCurrnetOffset = 0;
while (inputBufferCurrnetOffset < SrcSize)
{
UINT32 numberOfBytesToCopy = SrcSize - inputBufferCurrnetOffset;
inputBufferId = sys->fnAMediaCodec_dequeueInputBuffer(sys->decoder, -1);
if (inputBufferId < 0)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_dequeueInputBuffer failed [%d]",
inputBufferId);
// TODO: sleep?
continue;
}
inputBuffer =
sys->fnAMediaCodec_getInputBuffer(sys->decoder, inputBufferId, &inputBufferSize);
if (inputBuffer == NULL)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_getInputBuffer failed");
return -1;
}
if (numberOfBytesToCopy > inputBufferSize)
{
WLog_Print(h264->log, WLOG_WARN,
"MediaCodec inputBufferSize: got [%d] but wanted [%d]", inputBufferSize,
numberOfBytesToCopy);
numberOfBytesToCopy = inputBufferSize;
}
memcpy(inputBuffer, pSrcData + inputBufferCurrnetOffset, numberOfBytesToCopy);
inputBufferCurrnetOffset += numberOfBytesToCopy;
status = sys->fnAMediaCodec_queueInputBuffer(sys->decoder, inputBufferId, 0,
numberOfBytesToCopy, 0, 0);
if (status != AMEDIA_OK)
{
WLog_Print(h264->log, WLOG_ERROR, "Error AMediaCodec_queueInputBuffer %d", status);
return -1;
}
}
while (true)
{
AMediaCodecBufferInfo bufferInfo;
ssize_t outputBufferId =
sys->fnAMediaCodec_dequeueOutputBuffer(sys->decoder, &bufferInfo, -1);
if (outputBufferId >= 0)
{
sys->currentOutputBufferIndex = outputBufferId;
uint8_t* outputBuffer;
outputBuffer = sys->fnAMediaCodec_getOutputBuffer(sys->decoder, outputBufferId,
&outputBufferSize);
sys->currentOutputBufferIndex = outputBufferId;
if (outputBufferSize != (sys->width * sys->height +
((sys->width + 1) / 2) * ((sys->height + 1) / 2) * 2))
{
WLog_Print(h264->log, WLOG_ERROR, "Error unexpected output buffer size %d",
outputBufferSize);
return -1;
}
// TODO: work with AImageReader and get AImage object instead of
// COLOR_FormatYUV420Planar buffer.
iStride[0] = sys->width;
iStride[1] = (sys->width + 1) / 2;
iStride[2] = (sys->width + 1) / 2;
pYUVData[0] = outputBuffer;
pYUVData[1] = outputBuffer + iStride[0] * sys->height;
pYUVData[2] =
outputBuffer + iStride[0] * sys->height + iStride[1] * ((sys->height + 1) / 2);
break;
}
else if (outputBufferId == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED)
{
AMediaFormat* outputFormat;
outputFormat = sys->fnAMediaCodec_getOutputFormat(sys->decoder);
if (outputFormat == NULL)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_getOutputFormat failed");
return -1;
}
set_mediacodec_format(h264, &sys->outputFormat, outputFormat);
media_format = sys->fnAMediaFormat_toString(sys->outputFormat);
if (media_format == NULL)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaFormat_toString failed");
return -1;
}
}
else if (outputBufferId == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
{
WLog_Print(h264->log, WLOG_WARN,
"AMediaCodec_dequeueOutputBuffer need to try again later");
// TODO: sleep?
}
else if (outputBufferId == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)
{
WLog_Print(h264->log, WLOG_WARN,
"AMediaCodec_dequeueOutputBuffer returned deprecated value "
"AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED, ignoring");
}
else
{
WLog_Print(h264->log, WLOG_ERROR,
"AMediaCodec_dequeueOutputBuffer returned unknown value [%d]",
outputBufferId);
return -1;
}
}
break;
}
return 1;
}
static void mediacodec_uninit(H264_CONTEXT* h264)
{
media_status_t status = AMEDIA_OK;
H264_CONTEXT_MEDIACODEC* sys;
WINPR_ASSERT(h264);
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
WLog_Print(h264->log, WLOG_DEBUG, "Uninitializing MediaCodec");
if (!sys)
return;
if (sys->decoder != NULL)
{
release_current_outputbuffer(h264);
status = sys->fnAMediaCodec_stop(sys->decoder);
if (status != AMEDIA_OK)
{
WLog_Print(h264->log, WLOG_ERROR, "Error AMediaCodec_stop %d", status);
}
status = sys->fnAMediaCodec_delete(sys->decoder);
if (status != AMEDIA_OK)
{
WLog_Print(h264->log, WLOG_ERROR, "Error AMediaCodec_delete %d", status);
}
sys->decoder = NULL;
}
set_mediacodec_format(h264, &sys->inputFormat, NULL);
set_mediacodec_format(h264, &sys->outputFormat, NULL);
unload_libmediandk(h264);
free(sys);
h264->pSystemData = NULL;
}
static BOOL mediacodec_init(H264_CONTEXT* h264)
{
H264_CONTEXT_MEDIACODEC* sys;
media_status_t status;
const char* media_format;
char* codec_name;
AMediaFormat *inputFormat, *outputFormat;
WINPR_ASSERT(h264);
if (h264->Compressor)
{
WLog_Print(h264->log, WLOG_ERROR, "MediaCodec is not supported as an encoder");
goto EXCEPTION;
}
WLog_Print(h264->log, WLOG_DEBUG, "Initializing MediaCodec");
sys = (H264_CONTEXT_MEDIACODEC*)calloc(1, sizeof(H264_CONTEXT_MEDIACODEC));
if (!sys)
{
goto EXCEPTION;
}
h264->pSystemData = (void*)sys;
if (load_libmediandk(h264) < 0)
{
goto EXCEPTION;
}
sys->currentOutputBufferIndex = -1;
sys->width = sys->height = 0; // update when we're given the height and width
sys->decoder = sys->fnAMediaCodec_createDecoderByType("video/avc");
if (sys->decoder == NULL)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_createCodecByName failed");
goto EXCEPTION;
}
status = sys->fnAMediaCodec_getName(sys->decoder, &codec_name);
if (status != AMEDIA_OK)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_getName failed: %d", status);
goto EXCEPTION;
}
WLog_Print(h264->log, WLOG_DEBUG, "MediaCodec using video/avc codec [%s]", codec_name);
sys->fnAMediaCodec_releaseName(sys->decoder, codec_name);
sys->inputFormat = sys->fnAMediaFormat_new();
if (sys->inputFormat == NULL)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaFormat_new failed");
goto EXCEPTION;
}
sys->fnAMediaFormat_setString(sys->inputFormat, sys->gAMediaFormatKeyMime, "video/avc");
sys->fnAMediaFormat_setInt32(sys->inputFormat, sys->gAMediaFormatKeyWidth, sys->width);
sys->fnAMediaFormat_setInt32(sys->inputFormat, sys->gAMediaFormatKeyHeight, sys->height);
sys->fnAMediaFormat_setInt32(sys->inputFormat, sys->gAMediaFormatKeyColorFormat,
COLOR_FormatYUV420Planar);
media_format = sys->fnAMediaFormat_toString(sys->inputFormat);
if (media_format == NULL)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaFormat_toString failed");
goto EXCEPTION;
}
status = sys->fnAMediaCodec_configure(sys->decoder, sys->inputFormat, NULL, NULL, 0);
if (status != AMEDIA_OK)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_configure failed: %d", status);
goto EXCEPTION;
}
inputFormat = sys->fnAMediaCodec_getInputFormat(sys->decoder);
if (inputFormat == NULL)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_getInputFormat failed");
goto EXCEPTION;
}
set_mediacodec_format(h264, &sys->inputFormat, inputFormat);
media_format = sys->fnAMediaFormat_toString(sys->inputFormat);
if (media_format == NULL)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaFormat_toString failed");
goto EXCEPTION;
}
WLog_Print(h264->log, WLOG_DEBUG, "Using MediaCodec with input MediaFormat [%s]", media_format);
outputFormat = sys->fnAMediaCodec_getOutputFormat(sys->decoder);
if (outputFormat == NULL)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_getOutputFormat failed");
goto EXCEPTION;
}
set_mediacodec_format(h264, &sys->outputFormat, outputFormat);
media_format = sys->fnAMediaFormat_toString(sys->outputFormat);
if (media_format == NULL)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaFormat_toString failed");
goto EXCEPTION;
}
WLog_Print(h264->log, WLOG_DEBUG, "Using MediaCodec with output MediaFormat [%s]",
media_format);
WLog_Print(h264->log, WLOG_DEBUG, "Starting MediaCodec");
status = sys->fnAMediaCodec_start(sys->decoder);
if (status != AMEDIA_OK)
{
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_start failed %d", status);
goto EXCEPTION;
}
return TRUE;
EXCEPTION:
mediacodec_uninit(h264);
return FALSE;
}
H264_CONTEXT_SUBSYSTEM g_Subsystem_mediacodec = { "MediaCodec", mediacodec_init, mediacodec_uninit,
mediacodec_decompress, mediacodec_compress };

View File

@ -1,117 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* H.264 Bitmap Compression
*
* Copyright 2015 Marc-André Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define NAL_UNKNOWN X264_NAL_UNKNOWN
#define NAL_SLICE X264_NAL_SLICE
#define NAL_SLICE_DPA X264_NAL_SLICE_DPA
#define NAL_SLICE_DPB X264_NAL_SLICE_DPB
#define NAL_SLICE_DPC X264_NAL_SLICE_DPC
#define NAL_SLICE_IDR X264_NAL_SLICE_IDR
#define NAL_SEI X264_NAL_SEI
#define NAL_SPS X264_NAL_SPS
#define NAL_PPS X264_NAL_PPS
#define NAL_AUD X264_NAL_AUD
#define NAL_FILLER X264_NAL_FILLER
#define NAL_PRIORITY_DISPOSABLE X264_NAL_PRIORITY_DISPOSABLE
#define NAL_PRIORITY_LOW X264_NAL_PRIORITY_LOW
#define NAL_PRIORITY_HIGH X264_NAL_PRIORITY_HIGH
#define NAL_PRIORITY_HIGHEST X264_NAL_PRIORITY_HIGHEST
#include <stdint.h>
#include <x264.h>
#include <freerdp/codec/h264.h>
#error "X264 backend not implemented, please review your configuration!"
struct _H264_CONTEXT_X264
{
void* dummy;
};
typedef struct _H264_CONTEXT_X264 H264_CONTEXT_X264;
static int x264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize)
{
// H264_CONTEXT_X264* sys = (H264_CONTEXT_X264*) h264->pSystemData;
return -1;
}
static int x264_compress(H264_CONTEXT* h264, const BYTE** ppSrcYuv, const UINT32* pStride,
BYTE** ppDstData, UINT32* pDstSize)
{
// H264_CONTEXT_X264* sys = (H264_CONTEXT_X264*) h264->pSystemData;
return -1;
}
static void x264_uninit(H264_CONTEXT* h264)
{
H264_CONTEXT_X264* sys = (H264_CONTEXT_X264*)h264->pSystemData;
if (sys)
{
free(sys);
h264->pSystemData = NULL;
}
}
static BOOL x264_init(H264_CONTEXT* h264)
{
H264_CONTEXT_X264* sys;
h264->numSystemData = 1;
sys = (H264_CONTEXT_X264*)calloc(h264->numSystemData, sizeof(H264_CONTEXT_X264));
if (!sys)
{
goto EXCEPTION;
}
h264->pSystemData = (void*)sys;
if (h264->Compressor)
{
}
else
{
}
return TRUE;
EXCEPTION:
x264_uninit(h264);
return FALSE;
}
H264_CONTEXT_SUBSYSTEM g_Subsystem_x264 = { "x264", x264_init, x264_uninit, x264_decompress,
x264_compress };
#undef NAL_UNKNOWN
#undef NAL_SLICE
#undef NAL_SLICE_DPA
#undef NAL_SLICE_DPB
#undef NAL_SLICE_DPC
#undef NAL_SLICE_IDR
#undef NAL_SEI
#undef NAL_SPS
#undef NAL_PPS
#undef NAL_AUD
#undef NAL_FILLER
#undef NAL_PRIORITY_DISPOSABLE
#undef NAL_PRIORITY_LOW
#undef NAL_PRIORITY_HIGH
#undef NAL_PRIORITY_HIGHEST

View File

@ -23,6 +23,7 @@
#include "config.h"
#endif
#include <assert.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/bitstream.h>
@ -40,6 +41,8 @@
#include "rfx_types.h"
#include "progressive.h"
#define WINPR_ASSERT(x) assert(x)
#define TAG FREERDP_TAG("codec.progressive")
struct _RFX_PROGRESSIVE_UPGRADE_STATE
@ -434,6 +437,36 @@ static INLINE BOOL progressive_tile_allocate(RFX_PROGRESSIVE_TILE* tile)
return rc;
}
static BOOL progressive_allocate_tile_cache(PROGRESSIVE_SURFACE_CONTEXT* surface)
{
size_t oldIndex;
WINPR_ASSERT(surface);
WINPR_ASSERT(surface->gridSize > 0);
oldIndex = surface->gridSize;
if (surface->tiles)
surface->gridSize *= 2;
{
void* tmp = realloc(surface->tiles, surface->gridSize * sizeof(RFX_PROGRESSIVE_TILE));
if (!tmp)
return FALSE;
surface->tiles = tmp;
memset(&surface->tiles[oldIndex], 0,
(surface->gridSize - oldIndex) * sizeof(RFX_PROGRESSIVE_TILE));
}
{
void* tmp = realloc(surface->updatedTileIndices, surface->gridSize * sizeof(UINT32));
if (!tmp)
return FALSE;
surface->updatedTileIndices = tmp;
memset(&surface->updatedTileIndices[oldIndex], 0,
(surface->gridSize - oldIndex) * sizeof(UINT32));
}
return TRUE;
}
static PROGRESSIVE_SURFACE_CONTEXT* progressive_surface_context_new(UINT16 surfaceId, UINT32 width,
UINT32 height)
{
@ -450,14 +483,10 @@ static PROGRESSIVE_SURFACE_CONTEXT* progressive_surface_context_new(UINT16 surfa
surface->gridWidth = (width + (64 - width % 64)) / 64;
surface->gridHeight = (height + (64 - height % 64)) / 64;
surface->gridSize = surface->gridWidth * surface->gridHeight;
surface->tiles = (RFX_PROGRESSIVE_TILE*)calloc(surface->gridSize, sizeof(RFX_PROGRESSIVE_TILE));
surface->updatedTileIndices = (UINT32*)calloc(surface->gridSize, sizeof(UINT32));
if (!surface->tiles || !surface->updatedTileIndices)
if (!progressive_allocate_tile_cache(surface))
{
free(surface->updatedTileIndices);
free(surface->tiles);
free(surface);
progressive_surface_context_free(surface);
return NULL;
}
for (x = 0; x < surface->gridSize; x++)
@ -549,8 +578,8 @@ static BOOL progressive_surface_tile_replace(PROGRESSIVE_SURFACE_CONTEXT* surfac
}
if (surface->numUpdatedTiles >= surface->gridSize)
{
WLog_ERR(TAG, "Invalid total tile count, maximum %" PRIu32, surface->gridSize);
return FALSE;
if (!progressive_allocate_tile_cache(surface))
return FALSE;
}
region->tiles[region->usedTiles++] = t;

View File

@ -181,7 +181,8 @@ BOOL freerdp_connect(freerdp* instance)
if (status)
status2 = freerdp_channels_pre_connect(instance->context->channels, instance);
if (settings->KeyboardLayout == KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002)
if (settings->KeyboardLayout == KBD_JAPANESE ||
settings->KeyboardLayout == KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002)
{
settings->KeyboardType = 7;
settings->KeyboardSubType = 2;

View File

@ -1,29 +0,0 @@
#!/bin/bash
#
# Android build confguration
#
# Note: This is a simple configuration to build all
# architectures in one rush.
# Since android 64 bit support was introduced with NDK API 21
# this is the minimal common denominator.
# If you require support for older NDK API levels,
# create seperate configurations for each NDK API level
# and architecture you want to support.
WITH_JPEG=0
WITH_OPENH264=1
WITH_OPENSSL=1
BUILD_DEPS=1
DEPS_ONLY=0
NDK_TARGET=21
JPEG_TAG=master
OPENH264_TAG=v1.8.0 # NOTE: NDK r15c or earlier needed in --openh624-ndk for v1.8.0
OPENSSL_TAG=OpenSSL_1_1_1j
SRC_DIR=$SCRIPT_PATH/..
BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs
BUILD_SRC=$SRC_DIR/build
CMAKE_BUILD_TYPE=Release
BUILD_ARCH="armeabi-v7a x86"

View File

@ -1,29 +0,0 @@
#!/bin/bash
#
# Android build confguration
#
# Note: This is a simple configuration to build all
# architectures in one rush.
# Since android 64 bit support was introduced with NDK API 21
# this is the minimal common denominator.
# If you require support for older NDK API levels,
# create seperate configurations for each NDK API level
# and architecture you want to support.
WITH_JPEG=0
WITH_OPENH264=1
WITH_OPENSSL=1
BUILD_DEPS=1
DEPS_ONLY=0
NDK_TARGET=21
JPEG_TAG=master
OPENH264_TAG=v1.8.0 # NOTE: NDK r15c or earlier needed in --openh624-ndk for v1.8.0
OPENSSL_TAG=OpenSSL_1_1_1j
SRC_DIR=$SCRIPT_PATH/..
BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs
BUILD_SRC=$SRC_DIR/build
CMAKE_BUILD_TYPE=Release
BUILD_ARCH="arm64-v8a x86_64"

View File

@ -1,292 +0,0 @@
#!/bin/bash
SCRIPT_PATH=$(dirname "${BASH_SOURCE[0]}")
SCRIPT_PATH=$(realpath "$SCRIPT_PATH")
if [ -z $BUILD_ARCH ]; then
BUILD_ARCH="armeabi-v7a x86 x86_64 arm64-v8a"
fi
if [ -z $NDK_TARGET ]; then
NDK_TARGET=21
fi
if [ -z $CMAKE_PROGRAM ]; then
CMAKE_PROGRAM=$(find $ANDROID_SDK/cmake -name cmake -type f -executable -print -quit)
fi
if [ -z $CCACHE ]; then
CCACHE=$(which ccache)
fi
if [ -z $ANDROID_NDK ]; then
ANDROID_NDK="missing"
fi
if [ -z $ANDROID_SDK ]; then
ANDROID_SDK="missing"
fi
if [ -z $BUILD_DST ]; then
BUILD_DST=$(pwd)/libs
fi
if [ -z $BUILD_SRC ]; then
BUILD_SRC=$(pwd)/src
fi
if [ -z $SCM_URL ]; then
SCM_URL="missing"
fi
if [ -z $SCM_TAG ]; then
SCM_TAG=master
fi
CLEAN_BUILD_DIR=0
function common_help {
echo "$(BASHSOURCE[0]) supports the following arguments:"
echo " --ndk The base directory of your android NDK defa"
echo " ANDROID_NDK=$ANDROID_NDK"
echo " --sdk The base directory of your android SDK defa"
echo " ANDROID_SDK=$ANDROID_SDK"
echo " --arch A list of architectures to build"
echo " BUILD_ARCH=$BUILD_ARCH"
echo " --dst The destination directory for include and library files"
echo " BUILD_DST=$BUILD_DST"
echo " --src The source directory for SCM checkout"
echo " BUILD_SRC=$BUILD_SRC"
echo " --url The SCM source url"
echo " SCM_URL=$SCM_URL"
echo " --tag The SCM branch or tag to check out"
echo " SCM_TAG=$SCM_TAG"
echo " --clean Clean the destination before build"
echo " --help Display this help"
exit 0
}
function common_run {
echo "[RUN] $@"
"$@"
RES=$?
if [[ $RES -ne 0 ]];
then
echo "[ERROR] $@ retured $RES"
exit 1
fi
}
function common_parse_arguments {
while [[ $# > 0 ]]
do
key="$1"
case $key in
--conf)
source "$2"
shift
;;
--target)
NDK_TARGET="$2"
shift
;;
--ndk)
ANDROID_NDK="$2"
shift
;;
--sdk)
ANDROID_SDK="$2"
CMAKE_PROGRAM=$(find $ANDROID_SDK/cmake -name cmake -type f -executable -print -quit)
shift
;;
--arch)
BUILD_ARCH="$2"
shift
;;
--dst)
BUILD_DST="$2"
shift
;;
--src)
BUILD_SRC="$2"
shift
;;
--url)
SCM_URL="$2"
shift
;;
--tag)
SCM_TAG="$2"
shift
;;
--clean)
CLEAN_BUILD_DIR=1
shift
;;
--help)
common_help
shift
;;
*) # Unknown
;;
esac
shift
done
}
function common_check_requirements {
if [[ ! -d $ANDROID_NDK ]];
then
echo "export ANDROID_NDK to point to your NDK location."
exit 1
fi
if [[ ! -d $ANDROID_SDK ]];
then
echo "export ANDROID_SDK to point to your SDK location."
exit 1
fi
if [[ -z $BUILD_DST ]];
then
echo "Destination directory not valid"
exit 1
fi
if [[ -z $BUILD_SRC ]];
then
echo "Source directory not valid"
exit 1
fi
if [[ -z $SCM_URL ]];
then
echo "Source URL not defined! Define SCM_URL"
exit 1
fi
if [[ -z $SCM_TAG ]];
then
echo "SCM TAG / BRANCH not defined! Define SCM_TAG"
exit 1
fi
if [[ -z $NDK_TARGET ]];
then
echo "Android platform NDK_TARGET not defined"
exit 1
fi
if [ -x $ANDROID_NDK/ndk-build ]; then
NDK_BUILD=$ANDROID_NDK/ndk-build
else
echo "ndk-build not found in NDK directory $ANDROID_NDK"
echo "assuming ndk-build is in path..."
NDK_BUILD=ndk-build
fi
if [ -z $CMAKE_PROGRAM ]; then
CMAKE_PROGRAM=$(find $ANDROID_SDK/cmake -name cmake -type f -executable -print -quit)
fi
for CMD in make git $CMAKE_PROGRAM $NDK_BUILD
do
if ! type $CMD >/dev/null; then
echo "Command $CMD not found. Install and add it to the PATH."
exit 1
fi
done
if [ "${BUILD_SRC:0:1}" != "/" ];
then
BUILD_SRC=$(pwd)/$BUILD_SRC
fi
if [ "${BUILD_DST:0:1}" != "/" ];
then
BUILD_DST=$(pwd)/$BUILD_DST
fi
}
function common_update {
if [ $# -ne 3 ];
then
echo "Invalid arguments to update function $@"
exit 1
fi
SCM_URL=$1
SCM_TAG=$2
BUILD_SRC=$3
echo "Preparing checkout..."
BASE=$(pwd)
CACHE=$SCRIPT_PATH/../cache
common_run mkdir -p $CACHE
TARFILE="$CACHE/$SCM_TAG.tar.gz"
if [[ ! -f "$TARFILE" ]];
then
common_run wget -O "$TARFILE" "$SCM_URL/archive/$SCM_TAG.tar.gz"
fi
if [[ -d $BUILD_SRC ]];
then
common_run rm -rf $BUILD_SRC
fi
common_run mkdir -p $BUILD_SRC
common_run cd $BUILD_SRC
common_run tar zxf "$TARFILE" --strip 1
common_run cd $BASE
}
function common_clean {
if [ $CLEAN_BUILD_DIR -ne 1 ];
then
return
fi
if [ $# -ne 1 ];
then
echo "Invalid arguments to clean function $@"
exit 1
fi
echo "Cleaning up $1..."
common_run rm -rf $1
}
function common_copy {
if [ $# -ne 2 ];
then
echo "Invalid arguments to copy function $@"
exit 1
fi
if [ ! -d $1 ] || [ ! -d $1/include ] || [ ! -d $1/libs ];
then
echo "Invalid source $1"
exit 1
fi
if [ -z $2 ];
then
echo "Invalid destination $2"
exit 1
fi
if [ ! -d $2 ];
then
common_run mkdir -p $2
fi
common_run cp -L -r $1/include $2
common_run cp -L -r $1/libs/* $2
}

View File

@ -1,168 +0,0 @@
#!/bin/bash
JPEG_TAG=master
OPENH264_TAG=master
OPENSSL_TAG=master
WITH_JPEG=0
WITH_OPENH264=0
WITH_OPENSSL=0
SRC_DIR=$(dirname "${BASH_SOURCE[0]}")
SRC_DIR=$(realpath "$SRC_DIR")
BUILD_SRC=$(pwd)
BUILD_DST=$(pwd)
CMAKE_BUILD_TYPE=Debug
BUILD_DEPS=0
SCRIPT_PATH=$(dirname "${BASH_SOURCE[0]}")
source $SCRIPT_PATH/android-build-common.sh
source $SCRIPT_PATH/android-build.conf
# Parse arguments.
REMAINING=""
while [[ $# > 0 ]]
do
key="$1"
case $key in
--freerdp-src)
SRC_DIR="$2"
shift
;;
--jpeg)
WITH_JPEG=1
shift
;;
--openh264)
WITH_OPENH264=1
shift
;;
--openh264-ndk)
shift
ANDROID_NDK_OPENH264=$1
shift
;;
--openssl)
WITH_OPENSSL=1
shift
;;
--debug)
CMAKE_BUILD_TYPE=Debug
shift
;;
--release)
CMAKE_BUILD_TYPE=Release
shift
;;
--relWithDebug)
CMAKE_BUILD_TYPE=RelWithDebug
shift
;;
--build-deps)
BUILD_DEPS=1
shift
;;
*)
REMAINING="$REMAINING $key"
shift
;;
esac
done
common_parse_arguments $REMAINING
# clean up top
if [ -d $BUILD_SRC ];
then
common_clean $BUILD_SRC
fi
if [ -d $BUILD_DST ];
then
common_run mkdir -p $BUILD_DST
fi
# Prepare the environment
common_run mkdir -p $BUILD_SRC
CMAKE_CMD_ARGS="-DANDROID_NDK=$ANDROID_NDK \
-DANDROID_NATIVE_API_LEVEL=android-${NDK_TARGET} \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE \
-DFREERDP_EXTERNAL_PATH=$BUILD_DST \
-DCMAKE_MAKE_PROGRAM=make"
BASE=$(pwd)
for ARCH in $BUILD_ARCH
do
# build dependencies.
if [ $WITH_JPEG -ne 0 ];
then
if [ $BUILD_DEPS -ne 0 ];
then
common_run bash $SCRIPT_PATH/android-build-jpeg.sh \
--src $BUILD_SRC/jpeg --dst $BUILD_DST \
--ndk $ANDROID_NDK \
--arch $ARCH \
--target $NDK_TARGET \
--tag $JPEG_TAG
fi
CMAKE_CMD_ARGS="$CMAKE_CMD_ARGS -DWITH_JPEG=ON"
else
CMAKE_CMD_ARGS="$CMAKE_CMD_ARGS -DWITH_JPEG=OFF"
fi
if [ $WITH_OPENH264 -ne 0 ];
then
if [ -z "$ANDROID_NDK_OPENH264" ]
then
echo
echo "Warning: Missing openh264-ndk, using $ANDROID_NDK" >&2
echo
ANDROID_NDK_OPENH264=$ANDROID_NDK
fi
if [ $BUILD_DEPS -ne 0 ];
then
common_run bash $SCRIPT_PATH/android-build-openh264.sh \
--src $BUILD_SRC/openh264 --dst $BUILD_DST \
--sdk "$ANDROID_SDK" \
--ndk "$ANDROID_NDK_OPENH264" \
--arch $ARCH \
--target $NDK_TARGET \
--tag $OPENH264_TAG
fi
CMAKE_CMD_ARGS="$CMAKE_CMD_ARGS -DWITH_OPENH264=ON"
else
CMAKE_CMD_ARGS="$CMAKE_CMD_ARGS -DWITH_OPENH264=OFF"
fi
if [ $WITH_OPENSSL -ne 0 ];
then
if [ $BUILD_DEPS -ne 0 ];
then
common_run bash $SCRIPT_PATH/android-build-openssl.sh \
--src $BUILD_SRC/openssl --dst $BUILD_DST \
--sdk "$ANDROID_SDK" \
--ndk $ANDROID_NDK \
--arch $ARCH \
--target $NDK_TARGET \
--tag $OPENSSL_TAG
fi
fi
# Build and install the library.
if [ $DEPS_ONLY -eq 0 ];
then
common_run cd $BASE
common_run mkdir -p $BUILD_SRC/freerdp-build/$ARCH
common_run cd $BUILD_SRC/freerdp-build/$ARCH
common_run export ANDROID_NDK=$ANDROID_NDK
common_run $CMAKE_PROGRAM $CMAKE_CMD_ARGS \
-DANDROID_ABI=$ARCH \
-DCMAKE_INSTALL_PREFIX=$BUILD_DST/$ARCH \
-DCMAKE_INSTALL_LIBDIR=. \
$SRC_DIR
echo $(pwd)
common_run cmake --build . --target install
fi
done
echo "Successfully build library for architectures $BUILD_ARCH"

View File

@ -1,40 +0,0 @@
#!/bin/bash
SCM_URL=https://github.com/akallabeth/jpeg8d
SCM_TAG=master
source $(dirname "${BASH_SOURCE[0]}")/android-build-common.sh
function usage {
echo $0 [arguments]
echo "\tThe script checks out the OpenH264 git repository"
echo "\tto a local source directory, builds and installs"
echo "\tthe library for all architectures defined to"
echo "\tthe destination directory."
echo ""
echo "\t[-s|--source-dir <path>]"
echo "\t[-d|--destination-dir <path>]"
echo "\t[-a|--arch <architectures>]"
echo "\t[-t|--tag <tag or branch>]"
echo "\t[--scm-url <url>]"
echo "\t[--ndk <android NDK path>]"
echo "\t[--sdk <android SDK path>]"
exit 1
}
function build {
echo "Building architectures $BUILD_ARCH..."
BASE=$(pwd)
common_run cd $BUILD_SRC
common_run $NDK_BUILD V=1 APP_ABI="${BUILD_ARCH}" NDK_TOOLCHAIN_VERSION=4.9 -j clean
common_run $NDK_BUILD V=1 APP_ABI="${BUILD_ARCH}" NDK_TOOLCHAIN_VERSION=4.9 -j
common_run cd $BASE
}
# Run the main program.
common_parse_arguments $@
common_check_requirements
common_update $SCM_URL $SCM_TAG $BUILD_SRC
build
common_copy $BUILD_SRC $BUILD_DST

View File

@ -1,64 +0,0 @@
#!/bin/bash
SCM_URL=https://github.com/cisco/openh264
SCM_TAG=master
source $(dirname "${BASH_SOURCE[0]}")/android-build-common.sh
function build {
echo "Building architecture $1..."
BASE=$(pwd)
common_run cd $BUILD_SRC
PATH=$ANDROID_NDK:$PATH
MAKE="make PATH=$PATH ENABLEPIC=Yes OS=android NDKROOT=$ANDROID_NDK TARGET=android-$2 NDKLEVEL=$2 ARCH=$1 -j libraries"
common_run export QUIET_AR="$CCACHE "
common_run export QUIET_ASM="$CCACHE "
common_run export QUIET_CC="$CCACHE "
common_run export QUIET_CCAR="$CCACHE "
common_run export QUIET_CXX="$CCACHE "
common_run $MAKE -j
# Install creates a non optimal directory layout, fix that
common_run $MAKE PREFIX=$BUILD_SRC/libs/$1 install
common_run cd $BASE
}
# Run the main program.
common_parse_arguments $@
common_check_requirements
common_update $SCM_URL $SCM_TAG $BUILD_SRC
for ARCH in $BUILD_ARCH
do
case $ARCH in
"armeabi")
OARCH="arm"
;;
"armeabi-v7a")
OARCH="arm"
;;
"arm64-v8a")
OARCH="arm64"
;;
*)
OARCH=$ARCH
;;
esac
echo "$ARCH=$OARCH"
build $OARCH $NDK_TARGET
if [ ! -d $BUILD_DST/$ARCH/include ];
then
common_run mkdir -p $BUILD_DST/$ARCH/include
fi
common_run cp -L -r $BUILD_SRC/libs/$OARCH/include/ $BUILD_DST/$ARCH/
if [ ! -d $BUILD_DST/$ARCH ];
then
common_run mkdir -p $BUILD_DST/$ARCH
fi
common_run cp -L $BUILD_SRC/libs/$OARCH/lib/*.so $BUILD_DST/$ARCH/
done

View File

@ -1,77 +0,0 @@
#!/bin/bash
SCM_URL=https://github.com/openssl/openssl
SCM_TAG=master
COMPILER=4.9
source $(dirname "${BASH_SOURCE[0]}")/android-build-common.sh
function build {
if [ $# -ne 2 ];
then
echo "Invalid arguments $@"
exit 1
fi
CONFIG=$1
DST_PREFIX=$2
common_run export CC=clang
common_run export PATH=$(${SCRIPT_PATH}/toolchains_path.py --ndk ${ANDROID_NDK}):$ORG_PATH
common_run export ANDROID_NDK
echo "CONFIG=$CONFIG"
echo "DST_PREFIX=$DST_PREFIX"
echo "PATH=$PATH"
BASE=$(pwd)
DST_DIR=$BUILD_DST/$DST_PREFIX
common_run cd $BUILD_SRC
common_run ./Configure ${CONFIG} -D__ANDROID_API__=$NDK_TARGET
common_run make SHLIB_EXT=.so -j build_libs
if [ ! -d $DST_DIR ];
then
common_run mkdir -p $DST_DIR
fi
common_run cp *.so $DST_DIR/
common_run cd $BASE
}
# Run the main program.
common_parse_arguments $@
common_check_requirements
common_update $SCM_URL $SCM_TAG $BUILD_SRC
ORG_PATH=$PATH
for ARCH in $BUILD_ARCH
do
case $ARCH in
"armeabi-v7a")
build "android-arm" "armeabi-v7a"
;;
"x86")
build "android-x86" "x86"
;;
"arm64-v8a")
build "android-arm64" "arm64-v8a"
;;
"x86_64")
build "android-x86_64" "x86_64"
;;
*)
echo "[WARNING] Skipping unsupported architecture $ARCH"
continue
;;
esac
done
if [ ! -d $BUILD_DST/$ARCH/include ];
then
common_run mkdir -p $BUILD_DST/$ARCH/include
fi
common_run cp -L -R $BUILD_SRC/include/openssl $BUILD_DST/$ARCH/include/

View File

@ -1,29 +0,0 @@
#!/bin/bash
#
# Android build confguration
#
# Note: This is a simple configuration to build all
# architectures in one rush.
# Since android 64 bit support was introduced with NDK API 21
# this is the minimal common denominator.
# If you require support for older NDK API levels,
# create seperate configurations for each NDK API level
# and architecture you want to support.
WITH_JPEG=0
WITH_OPENH264=0
WITH_OPENSSL=1
BUILD_DEPS=1
DEPS_ONLY=0
NDK_TARGET=26
JPEG_TAG=master
OPENH264_TAG=v1.8.0 # NOTE: NDK r15c or earlier needed in --openh624-ndk for v1.8.0
OPENSSL_TAG=OpenSSL_1_1_1j
SRC_DIR=$SCRIPT_PATH/..
BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs
BUILD_SRC=$SRC_DIR/build
CMAKE_BUILD_TYPE=Debug
BUILD_ARCH="armeabi-v7a x86 arm64-v8a x86_64"

View File

@ -255,6 +255,14 @@ struct uwac_window
int pointer_current_cursor;
};
/**@brief data to pass to wl_buffer release listener */
struct uwac_buffer_release_data
{
UwacWindow* window;
int bufferIdx;
};
typedef struct uwac_buffer_release_data UwacBufferReleaseData;
/* in uwa-display.c */
UwacEvent* UwacDisplayNewEvent(UwacDisplay* d, int type);
int UwacDisplayWatchFd(UwacDisplay* display, int fd, uint32_t events, UwacTask* task);

View File

@ -46,7 +46,8 @@ static int bppFromShmFormat(enum wl_shm_format format)
static void buffer_release(void* data, struct wl_buffer* buffer)
{
UwacBuffer* uwacBuffer = (UwacBuffer*)data;
UwacBufferReleaseData* releaseData = data;
UwacBuffer* uwacBuffer = &releaseData->window->buffers[releaseData->bufferIdx];
uwacBuffer->used = false;
}
@ -64,7 +65,10 @@ static void UwacWindowDestroyBuffers(UwacWindow* w)
#else
region16_uninit(&buffer->damage);
#endif
UwacBufferReleaseData* releaseData =
(UwacBufferReleaseData*)wl_buffer_get_user_data(buffer->wayland_buffer);
wl_buffer_destroy(buffer->wayland_buffer);
free(releaseData);
munmap(buffer->data, buffer->size);
}
@ -342,7 +346,8 @@ int UwacWindowShmAllocBuffers(UwacWindow* w, int nbuffers, int allocSize, uint32
for (i = 0; i < nbuffers; i++)
{
UwacBuffer* buffer = &w->buffers[w->nbuffers + i];
int bufferIdx = w->nbuffers + i;
UwacBuffer* buffer = &w->buffers[bufferIdx];
#ifdef HAVE_PIXMAN_REGION
pixman_region32_init(&buffer->damage);
#else
@ -352,7 +357,10 @@ int UwacWindowShmAllocBuffers(UwacWindow* w, int nbuffers, int allocSize, uint32
buffer->size = allocSize;
buffer->wayland_buffer =
wl_shm_pool_create_buffer(pool, allocSize * i, width, height, w->stride, format);
wl_buffer_add_listener(buffer->wayland_buffer, &buffer_listener, buffer);
UwacBufferReleaseData* listener_data = xmalloc(sizeof(UwacBufferReleaseData));
listener_data->window = w;
listener_data->bufferIdx = bufferIdx;
wl_buffer_add_listener(buffer->wayland_buffer, &buffer_listener, listener_data);
}
wl_shm_pool_destroy(pool);

View File

@ -51,7 +51,7 @@ if (NOT WIN32)
endif()
# Soname versioning
set(RAW_VERSION_STRING "2.5.0")
set(RAW_VERSION_STRING "2.6.0")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)

View File

@ -30,7 +30,7 @@ endif(NOT WITH_ICU)
if (WITH_ICU)
find_package(ICU REQUIRED i18n uc io)
include_directories(${ICU_INCLUDE_DIRS})
winpr_include_directory_add(${ICU_INCLUDE_DIRS})
winpr_library_add_private(${ICU_LIBRARIES})
endif (WITH_ICU)

View File

@ -21,8 +21,11 @@
#include "config.h"
#endif
#include <assert.h>
#include <winpr/sspicli.h>
#define WINPR_ASSERT(x) assert(x)
/**
* sspicli.dll:
*
@ -60,6 +63,12 @@
#include <unistd.h>
#endif
#if defined(HAVE_GETPWUID_R)
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
#endif
#include <pthread.h>
#include <pwd.h>
@ -200,31 +209,33 @@ BOOL LogonUserExW(LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword
BOOL GetUserNameExA(EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
{
size_t length;
char login[MAX_PATH];
WINPR_ASSERT(lpNameBuffer);
WINPR_ASSERT(nSize);
switch (NameFormat)
{
case NameSamCompatible:
#ifndef HAVE_GETLOGIN_R
strncpy(login, getlogin(), sizeof(login));
#else
if (getlogin_r(login, sizeof(login)) != 0)
#if defined(HAVE_GETPWUID_R)
{
int rc;
struct passwd pwd = { 0 };
struct passwd* result = NULL;
uid_t uid = getuid();
rc = getpwuid_r(uid, &pwd, lpNameBuffer, *nSize, &result);
if (rc != 0)
return FALSE;
if (result == NULL)
return FALSE;
}
#elif defined(HAVE_GETLOGIN_R)
if (getlogin_r(lpNameBuffer, *nSize) != 0)
return FALSE;
#else
strncpy(lpNameBuffer, getlogin(), *nSize);
#endif
length = strlen(login);
if (*nSize >= length)
{
CopyMemory(lpNameBuffer, login, length + 1);
return TRUE;
}
else
{
*nSize = length + 1;
}
break;
*nSize = strnlen(lpNameBuffer, *nSize);
return TRUE;
case NameFullyQualifiedDN:
case NameDisplay:
@ -245,7 +256,29 @@ BOOL GetUserNameExA(EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG
BOOL GetUserNameExW(EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
{
return 0;
int res;
BOOL rc = FALSE;
char* name;
WINPR_ASSERT(nSize);
WINPR_ASSERT(lpNameBuffer);
name = calloc(1, *nSize + 1);
if (!name)
goto fail;
if (!GetUserNameExA(NameFormat, name, nSize))
goto fail;
res = ConvertToUnicode(CP_UTF8, 0, name, -1, &lpNameBuffer, *nSize);
if (res < 0)
goto fail;
*nSize = res + 1;
rc = TRUE;
fail:
free(name);
return rc;
}
#endif

View File

@ -1,15 +1,14 @@
#include <stdlib.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#define THREADS 24
#define THREADS 8
static DWORD WINAPI test_thread(LPVOID arg)
{
long timeout = 100 + (rand() % 1000);
long timeout = 30 + (rand() % 100);
WINPR_UNUSED(arg);
Sleep(timeout);
ExitThread(0);
@ -22,7 +21,7 @@ static int start_threads(DWORD count, HANDLE* threads)
for (i = 0; i < count; i++)
{
threads[i] = CreateThread(NULL, 0, test_thread, NULL, 0, NULL);
threads[i] = CreateThread(NULL, 0, test_thread, NULL, CREATE_SUSPENDED, NULL);
if (!threads[i])
{
@ -31,38 +30,45 @@ static int start_threads(DWORD count, HANDLE* threads)
}
}
for (i = 0; i < count; i++)
ResumeThread(threads[i]);
return 0;
}
static int close_threads(DWORD count, HANDLE* threads)
{
int rc = 0;
DWORD i;
for (i = 0; i < count; i++)
{
if (!threads[i])
continue;
if (!CloseHandle(threads[i]))
{
fprintf(stderr, "%s: CloseHandle [%" PRIu32 "] failure\n", __FUNCTION__, i);
return -1;
rc = -1;
}
threads[i] = NULL;
}
return 0;
return rc;
}
static BOOL TestWaitForAll(void)
{
BOOL rc = FALSE;
DWORD ret;
HANDLE threads[THREADS];
HANDLE threads[THREADS] = { 0 };
/* WaitForAll, timeout */
if (start_threads(THREADS, threads))
{
fprintf(stderr, "%s: start_threads failed\n", __FUNCTION__);
return FALSE;
goto fail;
}
ret = WaitForMultipleObjects(THREADS, threads, TRUE, 50);
ret = WaitForMultipleObjects(THREADS, threads, TRUE, 10);
if (ret != WAIT_TIMEOUT)
{
fprintf(stderr, "%s: WaitForMultipleObjects bWaitAll, timeout 50 failed, ret=%d\n",
@ -76,14 +82,14 @@ static BOOL TestWaitForAll(void)
goto fail;
}
rc = TRUE;
fail:
if (close_threads(THREADS, threads))
{
fprintf(stderr, "%s: close_threads failed\n", __FUNCTION__);
return FALSE;
}
rc = TRUE;
fail:
return rc;
}
@ -91,12 +97,12 @@ static BOOL TestWaitOne(void)
{
BOOL rc = FALSE;
DWORD ret;
HANDLE threads[THREADS];
HANDLE threads[THREADS] = { 0 };
/* WaitForAll, timeout */
if (start_threads(THREADS, threads))
{
fprintf(stderr, "%s: start_threads failed\n", __FUNCTION__);
return FALSE;
goto fail;
}
ret = WaitForMultipleObjects(THREADS, threads, FALSE, INFINITE);
@ -112,14 +118,14 @@ static BOOL TestWaitOne(void)
goto fail;
}
rc = TRUE;
fail:
if (close_threads(THREADS, threads))
{
fprintf(stderr, "%s: close_threads failed\n", __FUNCTION__);
return FALSE;
}
rc = TRUE;
fail:
return rc;
}
@ -127,15 +133,15 @@ static BOOL TestWaitOneTimeout(void)
{
BOOL rc = FALSE;
DWORD ret;
HANDLE threads[THREADS];
HANDLE threads[THREADS] = { 0 };
/* WaitForAll, timeout */
if (start_threads(THREADS, threads))
{
fprintf(stderr, "%s: start_threads failed\n", __FUNCTION__);
return FALSE;
goto fail;
}
ret = WaitForMultipleObjects(THREADS, threads, FALSE, 50);
ret = WaitForMultipleObjects(THREADS, threads, FALSE, 1);
if (ret != WAIT_TIMEOUT)
{
fprintf(stderr, "%s: WaitForMultipleObjects timeout 50 failed, ret=%d\n", __FUNCTION__,
@ -148,15 +154,14 @@ static BOOL TestWaitOneTimeout(void)
fprintf(stderr, "%s: WaitForMultipleObjects bWaitAll, INFINITE failed\n", __FUNCTION__);
goto fail;
}
rc = TRUE;
fail:
if (close_threads(THREADS, threads))
{
fprintf(stderr, "%s: close_threads failed\n", __FUNCTION__);
return FALSE;
}
rc = TRUE;
fail:
return rc;
}
@ -164,12 +169,12 @@ static BOOL TestWaitOneTimeoutMultijoin(void)
{
BOOL rc = FALSE;
DWORD ret, i;
HANDLE threads[THREADS];
HANDLE threads[THREADS] = { 0 };
/* WaitForAll, timeout */
if (start_threads(THREADS, threads))
{
fprintf(stderr, "%s: start_threads failed\n", __FUNCTION__);
return FALSE;
goto fail;
}
for (i = 0; i < THREADS; i++)
@ -177,7 +182,7 @@ static BOOL TestWaitOneTimeoutMultijoin(void)
ret = WaitForMultipleObjects(THREADS, threads, FALSE, 0);
if (ret != WAIT_TIMEOUT)
{
fprintf(stderr, "%s: WaitForMultipleObjects timeout 50 failed, ret=%d\n", __FUNCTION__,
fprintf(stderr, "%s: WaitForMultipleObjects timeout 0 failed, ret=%d\n", __FUNCTION__,
ret);
goto fail;
}
@ -189,34 +194,37 @@ static BOOL TestWaitOneTimeoutMultijoin(void)
goto fail;
}
rc = TRUE;
fail:
if (close_threads(THREADS, threads))
{
fprintf(stderr, "%s: close_threads failed\n", __FUNCTION__);
return FALSE;
}
rc = TRUE;
fail:
return rc;
}
static BOOL TestDetach(void)
{
HANDLE threads[THREADS];
BOOL rc = FALSE;
HANDLE threads[THREADS] = { 0 };
/* WaitForAll, timeout */
if (start_threads(THREADS, threads))
{
fprintf(stderr, "%s: start_threads failed\n", __FUNCTION__);
return FALSE;
goto fail;
}
rc = TRUE;
fail:
if (close_threads(THREADS, threads))
{
fprintf(stderr, "%s: close_threads failed\n", __FUNCTION__);
return FALSE;
}
return TRUE;
return rc;
}
int TestSynchMultipleThreads(int argc, char* argv[])

View File

@ -173,23 +173,29 @@ static void SamLookupFinish(WINPR_SAM* sam)
static void HexStrToBin(const char* str, BYTE* bin, size_t length)
{
size_t i;
CharUpperBuffA(str, length * 2);
for (i = 0; i < length; i++)
{
bin[i] = 0;
char cur = str[2 * i];
char curNext = str[2 * i + 1];
BYTE* curBin = &bin[i];
if ((str[i * 2] >= '0') && (str[i * 2] <= '9'))
bin[i] |= (str[i * 2] - '0') << 4;
CharUpperBuffA(&cur, 1);
CharUpperBuffA(&curNext, 1);
if ((str[i * 2] >= 'A') && (str[i * 2] <= 'F'))
bin[i] |= (str[i * 2] - 'A' + 10) << 4;
*curBin = 0;
if ((str[i * 2 + 1] >= '0') && (str[i * 2 + 1] <= '9'))
bin[i] |= (str[i * 2 + 1] - '0');
if ((cur >= '0') && (cur <= '9'))
*curBin |= (cur - '0') << 4;
if ((str[i * 2 + 1] >= 'A') && (str[i * 2 + 1] <= 'F'))
bin[i] |= (str[i * 2 + 1] - 'A' + 10);
if ((cur >= 'A') && (cur <= 'F'))
*curBin |= (cur - 'A' + 10) << 4;
if ((curNext >= '0') && (curNext <= '9'))
*curBin |= (curNext - '0');
if ((curNext >= 'A') && (curNext <= 'F'))
*curBin |= (curNext - 'A' + 10);
}
}