Merge branch 'master' of git://github.com/awakecoding/FreeRDP

This commit is contained in:
Benoît LeBlanc 2013-11-14 15:32:20 -05:00
commit ed3632f6f3
54 changed files with 1200 additions and 312 deletions

2
.gitignore vendored
View File

@ -5,7 +5,7 @@ CMakeCache.txt
config.h
install_manifest*.txt
CTestTestfile.cmake
freerdp.pc
*.pc
Makefile
Testing
cmake_install.cmake

View File

@ -273,7 +273,11 @@ endif(APPLE)
if(ANDROID)
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
add_definitions(-DNDK_DEBUG=1)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG}")
# NOTE: Manually add -gdwarf-3, as newer toolchains default to -gdwarf-4,
# which is not supported by the gdbserver binary shipped with
# the android NDK (tested with r9b)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG} -gdwarf-3")
endif()
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -llog")
if (NOT FREERDP_ANDROID_EXTERNAL_SSL_PATH)
@ -294,9 +298,12 @@ if(ANDROID)
endif()
endif()
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_ANDROID_EXTERNAL_SSL_PATH})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/client/Android/FreeRDPCore/libs/${ANDROID_ABI})
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/scripts/regenerate_jni_headers.sh.cmake
${CMAKE_CURRENT_SOURCE_DIR}/scripts/regenerate_jni_headers.sh @ONLY)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/client/Android/FreeRDPCore/jni/${ANDROID_ABI})
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/regenerate_jni_headers.sh.cmake
${CMAKE_BINARY_DIR}/scripts/regenerate_jni_headers.sh @ONLY)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/scripts/gprof_generate.sh.cmake
${CMAKE_BINARY_DIR}/scripts/gprof_generate.sh @ONLY)
endif()
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
@ -508,12 +515,6 @@ include_directories("${CMAKE_BINARY_DIR}/winpr/include")
add_subdirectory(winpr)
# Generate pkg-config
if(NOT MSVC)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp.pc.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()
if(WITH_CUNIT)
message(FATAL_ERROR "cunit (WITH_CUNIT) is deprecated please use BUILD_TESTING to build ctest tests.
The cunit directory contains the old tests and is kept until all tests are converted.")

View File

@ -335,6 +335,16 @@ int freerdp_channels_global_init(void)
int freerdp_channels_global_uninit(void)
{
EnterCriticalSection(&g_channels_lock);
DeleteCriticalSection(&g_channels_lock);
if (g_ChannelsList)
{
ArrayList_Lock(g_ChannelsList);
ArrayList_Free(g_ChannelsList);
g_ChannelsList = NULL;
}
return 0;
}
@ -356,7 +366,9 @@ void freerdp_channels_free(rdpChannels* channels)
{
MessagePipe_Free(channels->MsgPipe);
/* TODO: remove from channels list */
ArrayList_Lock(g_ChannelsList);
ArrayList_Remove(g_ChannelsList, channels);
ArrayList_Unlock(g_ChannelsList);
free(channels);
}
@ -496,8 +508,8 @@ int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
{
int index;
char* name;
char* hostname;
int hostnameLength;
char* hostname;
int hostnameLength;
CHANNEL_CLIENT_DATA* pChannelClientData;
channels->is_connected = 1;

View File

@ -661,7 +661,7 @@ void drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
drive->files = ListDictionary_New(TRUE);
ListDictionary_Object(drive->files)->fnObjectFree = (OBJECT_FREE_FN) drive_file_free;
drive->IrpQueue = MessageQueue_New();
drive->IrpQueue = MessageQueue_New(NULL);
drive->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_thread_func, drive, CREATE_SUSPENDED, NULL);
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) drive);
@ -735,8 +735,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
if (*dev > 'B')
{
/* Suppress disk drives A and B to avoid pesty messages */
_snprintf(buf, sizeof(buf) - 4, "%s", drive->Name);
len = strlen(buf);
len = _snprintf(buf, sizeof(buf) - 4, "%s", drive->Name);
buf[len] = '_';
buf[len + 1] = dev[0];
buf[len + 2] = 0;

View File

@ -327,7 +327,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
parallel->path = path;
parallel->queue = MessageQueue_New();
parallel->queue = MessageQueue_New(NULL);
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) parallel);

View File

@ -930,8 +930,6 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
{
MessagePipe_PostQuit(rdpsnd->MsgPipe, 0);
WaitForSingleObject(rdpsnd->thread, INFINITE);
MessagePipe_Free(rdpsnd->MsgPipe);
CloseHandle(rdpsnd->thread);
rdpsnd->channelEntryPoints.pVirtualChannelClose(rdpsnd->OpenHandle);

View File

@ -15,8 +15,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
set(ANDROID_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/aFreeRDP")
if (NOT ANDROID_NDK)
message(FATAL_ERROR "ANDROID_NDK not set but required for building android native library.")
endif()
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, BOTH)
find_program(NDK_COMMAND ndk-build)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER, ONLY)
if(NDK_COMMAND STREQUAL "ANT_COMMAND-NOTFOUND")
message(FATAL_ERROR "ndk-build not found but required to build native lib")
endif()
set(NDK_LIB_CFG "${CMAKE_CURRENT_BINARY_DIR}/FreeRDPCore/jni/Android.mk")
if(ANDROID_BUILD_JAVA)
if (NOT ANDROID_SDK)
message(FATAL_ERROR "ANDROID_SDK not set but required for building the java gui (ANDROID_BUILD_JAVA)")
@ -30,18 +41,20 @@ if(ANDROID_BUILD_JAVA)
if(ANT_COMMAND STREQUAL "ANT_COMMAND-NOTFOUND")
message(FATAL_ERROR "ant not found but required to build android java")
endif()
if(ANDROID_BUILD_JAVA_DEBUG)
set(ANDROID_BUILD_TYPE "debug")
else()
set(ANDROID_BUILD_TYPE "release")
endif()
endif(ANDROID_BUILD_JAVA)
if(ANDROID_BUILD_JAVA_DEBUG)
set(ANDROID_BUILD_TYPE "debug")
else()
set(ANDROID_BUILD_TYPE "release")
endif()
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
set(ANDROID_DEBUG_ENABLE "true")
set(NDK_DEBUG "1")
else()
set(ANDROID_DEBUG_ENABLE "false")
set(NDK_DEBUG "0")
endif()
add_subdirectory(FreeRDPCore)

View File

@ -5,6 +5,16 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.cdt.managedbuilder.core.genmakebuilder.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
@ -25,9 +35,19 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>

View File

@ -3,19 +3,29 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
package="com.freerdp.freerdpcore"
android:versionCode="2"
android:versionCode="@ANDROID_APP_VERSION@"
android:versionName="@GIT_REVISION@" >
<uses-sdk android:targetSdkVersion="@ANDROID_APP_TARGET_SDK@" android:minSdkVersion="@ANDROID_APP_MIN_SDK@"/>
<uses-sdk
android:targetSdkVersion="@ANDROID_APP_TARGET_SDK@"
android:minSdkVersion="@ANDROID_APP_MIN_SDK@"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<supports-screens android:anyDensity="true" android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" />
<supports-screens
android:anyDensity="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true" />
<application>
<application
android:debuggable="@ANDROID_DEBUG_ENABLE@">
<!-- Activity to create shortcuts -->
<activity android:name=".presentation.ShortcutsActivity"

View File

@ -17,7 +17,6 @@
# limitations under the License.
set(ANDROID_PACKAGE_NAME "aFreeRDPCore")
file(MAKE_DIRECTORY ${ANDROID_BINARY_DIR})
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake
${CMAKE_CURRENT_BINARY_DIR}/AndroidManifest.xml @ONLY)
@ -45,20 +44,5 @@ endif()
add_subdirectory(jni)
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin;obj;libs")
if(ANDROID_BUILD_JAVA)
file(MAKE_DIRECTORY "${ANDROID_BINARY_DIR}/bin")
set(ANDROIDLIB "${ANDROID_BINARY_DIR}/bin/classes.jar")
# command to create the android package
add_custom_command(
OUTPUT "${ANDROIDLIB}"
COMMAND ${ANT_COMMAND} ${ANDROID_BUILD_TYPE}
WORKING_DIRECTORY "${ANDROID_BINARY_DIR}"
MAIN_DEPENDENCY AndroidManifest.xml
DEPENDS freerdp-android
${CMAKE_CURRENT_BINARY_DIR}/local.properties
)
add_custom_target(android-lib ALL SOURCES "${ANDROIDLIB}")
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin")
endif()

View File

@ -0,0 +1,8 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := freerdp-android
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libfreerdp-android.so
LOCAL_EXPORT_C_INCLUDES := ../../../../include
include $(PREBUILT_SHARED_LIBRARY)

View File

@ -0,0 +1 @@
APP_ABI := @ANDROID_ABI@

View File

@ -19,10 +19,14 @@
set(MODULE_NAME "freerdp-android")
set(MODULE_PREFIX "FREERDP_CLIENT_ANDROID")
include_directories(.)
include_directories(generated)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Application.mk.cmake
${CMAKE_CURRENT_BINARY_DIR}/Application.mk @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Android.mk.cmake
${CMAKE_CURRENT_BINARY_DIR}/Android.mk @ONLY)
if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-sign")
endif()
@ -68,16 +72,11 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} jnigraphics)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_ABI}")
set_target_properties(${MODULE_NAME}
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${ANDROID_BINARY_DIR}/libs/${ANDROID_ABI}")
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_ABI}")
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Android")
get_property(LIB_ABSNAME TARGET ${MODULE_NAME} PROPERTY LOCATION)
file(MAKE_DIRECTORY ${ANDROID_BINARY_DIR}/obj/local/${ANDROID_NDK_ABI_NAME})
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${LIB_ABSNAME}
${ANDROID_BINARY_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/)

View File

@ -16,19 +16,15 @@
#include "config.h"
#endif
#include <android/log.h>
#define TAG "LibFreeRDP"
#define DEBUG_ANDROID_NULL(fmt, ...) do { } while (0)
#define DEBUG_ANDROID_PRINT(_dbg_str, fmt, ...) __android_log_print(ANDROID_LOG_INFO, TAG, _dbg_str fmt "\n" , __FUNCTION__, __LINE__, ## __VA_ARGS__)
#define DEBUG_ANDROID_CLASS(_dbg_class, fmt, ...) DEBUG_ANDROID_PRINT("DBG_" #_dbg_class " %s (%d): ", fmt, ## __VA_ARGS__)
#include <freerdp/utils/debug.h>
#ifdef WITH_DEBUG_ANDROID_JNI
#define DEBUG_ANDROID(fmt, ...) DEBUG_ANDROID_PRINT("DBG %s (%d): ", fmt, ## __VA_ARGS__)
#define DEBUG_ANDROID(fmt, ...) DEBUG_CLASS(JNI, fmt, ## __VA_ARGS__)
#else
#define DEBUG_ANDROID(fmt, ...) DEBUG_ANDROID_NULL(fmt, ## __VA_ARGS__)
#define DEBUG_ANDROID(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif
#endif /* FREERDP_ANDROID_DEBUG_H */

View File

@ -28,6 +28,8 @@
#include <freerdp/utils/event.h>
#include <freerdp/constants.h>
#include <freerdp/locale/keyboard.h>
#include <freerdp/primitives.h>
#include <freerdp/version.h>
#include <android/bitmap.h>
@ -42,12 +44,6 @@
#include "jni/prof.h"
#endif
struct thread_data
{
freerdp* instance;
};
int android_context_new(freerdp* instance, rdpContext* context)
{
context->channels = freerdp_channels_new();
@ -72,28 +68,33 @@ void android_begin_paint(rdpContext* context)
void android_end_paint(rdpContext* context)
{
androidContext *ctx = (androidContext*)context;
rdpSettings* settings = context->instance->settings;
DEBUG_ANDROID("ui_update");
rdpGdi *gdi = context->gdi;
if (gdi->primary->hdc->hwnd->invalid->null)
return;
assert(ctx);
assert(settings);
assert(context->instance);
int x = gdi->primary->hdc->hwnd->invalid->x;
int y = gdi->primary->hdc->hwnd->invalid->y;
int w = gdi->primary->hdc->hwnd->invalid->w;
int h = gdi->primary->hdc->hwnd->invalid->h;
DEBUG_ANDROID("ui_update: x:%d y:%d w:%d h:%d", x, y, w, h);
freerdp_callback("OnGraphicsUpdate", "(IIIII)V", context->instance, x, y, w, h);
DEBUG_ANDROID("width=%d, height=%d, bpp=%d", settings->DesktopWidth,
settings->DesktopHeight, settings->ColorDepth);
freerdp_callback("OnGraphicsUpdate", "(IIIII)V", context->instance,
0, 0, settings->DesktopWidth, settings->DesktopHeight);
}
void android_desktop_resize(rdpContext* context)
{
DEBUG_ANDROID("ui_desktop_resize");
rdpGdi *gdi = context->gdi;
freerdp_callback("OnGraphicsResize", "(IIII)V", context->instance, gdi->width, gdi->height, gdi->dstBpp);
assert(context);
assert(context->settings);
assert(context->instance);
freerdp_callback("OnGraphicsResize", "(IIII)V",
context->instance, context->settings->DesktopWidth,
context->settings->DesktopHeight, context->settings->ColorDepth);
}
@ -138,17 +139,24 @@ BOOL android_pre_connect(freerdp* instance)
return TRUE;
}
BOOL android_post_connect(freerdp* instance)
static BOOL android_post_connect(freerdp* instance)
{
rdpSettings *settings = instance->settings;
DEBUG_ANDROID("android_post_connect");
assert(instance);
assert(settings);
freerdp_callback("OnSettingsChanged", "(IIII)V", instance,
instance->settings->DesktopWidth, instance->settings->DesktopHeight,
instance->settings->ColorDepth);
settings->DesktopWidth, settings->DesktopHeight,
settings->ColorDepth);
instance->context->cache = cache_new(instance->settings);
instance->context->cache = cache_new(settings);
gdi_init(instance, CLRCONV_ALPHA | ((instance->settings->ColorDepth > 16) ? CLRBUF_32BPP : CLRBUF_16BPP), NULL);
gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT |
((instance->settings->ColorDepth > 16) ? CLRBUF_32BPP : CLRBUF_16BPP),
NULL);
instance->update->BeginPaint = android_begin_paint;
instance->update->EndPaint = android_end_paint;
@ -164,6 +172,13 @@ BOOL android_post_connect(freerdp* instance)
return TRUE;
}
static void android_post_disconnect(freerdp* instance)
{
gdi_free(instance);
cache_free(instance->context->cache);
android_cliprdr_uninit(instance);
}
BOOL android_authenticate(freerdp* instance, char** username, char** password, char** domain)
{
DEBUG_ANDROID("Authenticate user:");
@ -314,6 +329,9 @@ static void* jni_input_thread(void* arg)
do
{
DWORD rc = WaitForMultipleObjects(3, event, FALSE, INFINITE);
if ((rc < WAIT_OBJECT_0) || (rc > WAIT_OBJECT_0 + 2))
continue;
if (rc == WAIT_OBJECT_0 + 2)
{
wMessage msg;
@ -322,9 +340,6 @@ static void* jni_input_thread(void* arg)
if (msg.id == WMQ_QUIT)
break;
}
if ((rc < WAIT_OBJECT_0) && (rc > WAIT_OBJECT_0 + 1))
break;
if (android_check_fds(instance) != TRUE)
break;
}
@ -374,7 +389,7 @@ static int android_freerdp_run(freerdp* instance)
int rcount;
int wcount;
int fd_input_event;
HANDLE input_event;
HANDLE input_event = NULL;
void* rfds[32];
void* wfds[32];
fd_set rfds_set;
@ -413,7 +428,7 @@ static int android_freerdp_run(freerdp* instance)
(LPTHREAD_START_ROUTINE) jni_update_thread, instance, 0, NULL);
}
if (async_input)
if (async_input)
{
input_thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) jni_input_thread, instance, 0, NULL);
@ -521,7 +536,7 @@ static int android_freerdp_run(freerdp* instance)
break;
}
}
else
else if (input_event)
{
if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0)
{
@ -555,6 +570,13 @@ static int android_freerdp_run(freerdp* instance)
freerdp_channels_close(instance->context->channels, instance);
DEBUG_ANDROID("Cleanup threads...");
if (async_channels)
{
WaitForSingleObject(channels_thread, INFINITE);
CloseHandle(channels_thread);
}
if (async_update)
{
wMessageQueue* update_queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
@ -570,19 +592,9 @@ static int android_freerdp_run(freerdp* instance)
WaitForSingleObject(input_thread, INFINITE);
CloseHandle(input_thread);
}
if (async_channels)
{
WaitForSingleObject(channels_thread, INFINITE);
CloseHandle(channels_thread);
}
DEBUG_ANDROID("Disconnecting...");
freerdp_channels_free(instance->context->channels);
freerdp_disconnect(instance);
gdi_free(instance);
cache_free(instance->context->cache);
android_cliprdr_uninit(instance);
freerdp_callback("OnDisconnected", "(I)V", instance);
DEBUG_ANDROID("Quit.");
@ -590,19 +602,15 @@ static int android_freerdp_run(freerdp* instance)
return 0;
}
void* android_thread_func(void* param)
static void* android_thread_func(void* param)
{
struct thread_data* data;
data = (struct thread_data*) param;
assert(data);
assert(data->instance);
freerdp* instance = param;
DEBUG_ANDROID("Start.");
freerdp* instance = data->instance;
assert(instance);
android_freerdp_run(instance);
free(data);
DEBUG_ANDROID("Quit.");
@ -615,6 +623,7 @@ JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls)
freerdp* instance;
#if defined(WITH_GPROF)
setenv("CPUPROFILE_FREQUENCY", "200", 1);
monstartup("libfreerdp-android.so");
#endif
@ -622,6 +631,7 @@ JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls)
instance = freerdp_new();
instance->PreConnect = android_pre_connect;
instance->PostConnect = android_post_connect;
instance->PostDisconnect = android_post_disconnect;
instance->Authenticate = android_authenticate;
instance->VerifyCertificate = android_verify_certificate;
instance->VerifyChangedCertificate = android_verify_changed_certificate;
@ -640,6 +650,8 @@ JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls)
JNIEXPORT void JNICALL jni_freerdp_free(JNIEnv *env, jclass cls, jint instance)
{
freerdp* inst = (freerdp*)instance;
freerdp_context_free(inst);
freerdp_free(inst);
#if defined(WITH_GPROF)
@ -650,15 +662,13 @@ JNIEXPORT void JNICALL jni_freerdp_free(JNIEnv *env, jclass cls, jint instance)
JNIEXPORT jboolean JNICALL jni_freerdp_connect(JNIEnv *env, jclass cls, jint instance)
{
freerdp* inst = (freerdp*)instance;
struct thread_data* data = (struct thread_data*) malloc(sizeof(struct thread_data));
data->instance = inst;
androidContext* ctx = (androidContext*)inst->context;
assert(inst);
assert(data);
assert(inst->context);
assert(ctx);
androidContext* ctx = (androidContext*)inst->context;
pthread_create(&ctx->thread, 0, android_thread_func, data);
ctx->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)android_thread_func, inst, 0, NULL);
return JNI_TRUE;
}
@ -666,19 +676,27 @@ JNIEXPORT jboolean JNICALL jni_freerdp_connect(JNIEnv *env, jclass cls, jint ins
JNIEXPORT jboolean JNICALL jni_freerdp_disconnect(JNIEnv *env, jclass cls, jint instance)
{
freerdp* inst = (freerdp*)instance;
androidContext* ctx = (androidContext*)inst->context;
ANDROID_EVENT* event = (ANDROID_EVENT*)android_event_disconnect_new();
assert(inst);
assert(ctx);
assert(event);
android_push_event(inst, event);
WaitForSingleObject(ctx->thread, INFINITE);
CloseHandle(ctx->thread);
ctx->thread = NULL;
freerdp_callback("OnDisconnecting", "(I)V", instance);
return (jboolean) JNI_TRUE;
}
JNIEXPORT void JNICALL jni_freerdp_cancel_connection(JNIEnv *env, jclass cls, jint instance)
{
DEBUG_ANDROID("Cancelling connection ...");
freerdp* inst = (freerdp*)instance;
ANDROID_EVENT* event = (ANDROID_EVENT*)android_event_disconnect_new();
android_push_event(inst, event);
freerdp_callback("OnDisconnecting", "(I)V", instance);
jni_freerdp_disconnect(env, cls, instance);
}
JNIEXPORT void JNICALL jni_freerdp_set_data_directory(JNIEnv *env, jclass cls, jint instance, jstring jdirectory)
@ -1001,7 +1019,7 @@ JNIEXPORT void JNICALL jni_freerdp_set_gateway_info(JNIEnv *env, jclass cls, jin
(*env)->ReleaseStringUTFChars(env, jgatewaydomain, gatewaydomain);
}
void copy_pixel_buffer(UINT8* dstBuf, UINT8* srcBuf, int x, int y, int width, int height, int wBuf, int hBuf, int bpp)
static void copy_pixel_buffer(UINT8* dstBuf, UINT8* srcBuf, int x, int y, int width, int height, int wBuf, int hBuf, int bpp)
{
int i, j;
int length;

View File

@ -11,7 +11,6 @@
#define __ANDROID_FREERDP_H
#include <jni.h>
#include <pthread.h>
#include <freerdp/freerdp.h>
#include "android_event.h"
@ -21,18 +20,14 @@ struct android_context
rdpContext rdpCtx;
ANDROID_EVENT_QUEUE* event_queue;
pthread_t thread;
HANDLE thread;
BOOL is_connected;
void* clipboard_context;
};
typedef struct android_context androidContext;
void copy_remotefx_tile(UINT8* dstBuf, UINT8* srcBuf, int x, int y, int width, int height, int bpp);
void copy_pixel_buffer(UINT8* dstBuf, UINT8* srcBuf, int x, int y, int width, int height, int wBuf, int hBuf, int bpp);
JNIEXPORT jint JNICALL jni_freerdp_new(JNIEnv *env, jclass cls);
JNIEXPORT void JNICALL jni_freerdp_free(JNIEnv *env, jclass cls, jint instance);
JNIEXPORT jboolean JNICALL jni_freerdp_connect(JNIEnv *env, jclass cls, jint instance);

View File

@ -13,7 +13,6 @@
#endif
#include <stdio.h>
#include <android/log.h>
#include "android_jni_callback.h"
#include "android_debug.h"
@ -36,24 +35,30 @@ void jni_load_class(JNIEnv *env, const char *path, jobject *objptr)
if (!class)
{
DEBUG_ANDROID("jni_load_class: failed to find class %s", path);
DEBUG_WARN("jni_load_class: failed to find class %s", path);
goto finish;
}
method = (*env)->GetMethodID(env, class, "<init>", "()V");
if (!method)
{
DEBUG_ANDROID("jni_load_class: failed to find class constructor of %s", path);
DEBUG_WARN("jni_load_class: failed to find class constructor of %s", path);
goto finish;
}
object = (*env)->NewObject(env, class, method);
if (!object)
{
DEBUG_ANDROID("jni_load_class: failed create new object of %s", path);
DEBUG_WARN("jni_load_class: failed create new object of %s", path);
goto finish;
}
(*objptr) = (*env)->NewGlobalRef(env, object);
finish:
while(0);
}
jint init_callback_environment(JavaVM* vm)
@ -61,7 +66,7 @@ jint init_callback_environment(JavaVM* vm)
JNIEnv* env;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
{
DEBUG_ANDROID("JNI_OnLoad: failed to obtain current JNI environment");
DEBUG_WARN("JNI_OnLoad: failed to obtain current JNI environment");
return -1;
}
@ -83,7 +88,7 @@ jboolean jni_attach_thread(JNIEnv** env)
if ((*jVM)->GetEnv(jVM, (void**) env, JNI_VERSION_1_4) != JNI_OK)
{
DEBUG_ANDROID("android_java_callback: failed to obtain current JNI environment");
DEBUG_WARN("android_java_callback: failed to obtain current JNI environment");
}
return JNI_TRUE;
@ -113,17 +118,20 @@ void java_callback_void(jobject obj, const char * callback, const char* signatur
jObjClass = (*env)->GetObjectClass(env, obj);
if (!jObjClass) {
DEBUG_ANDROID("android_java_callback: failed to get class reference");
DEBUG_WARN("android_java_callback: failed to get class reference");
goto finish;
}
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
if (!jCallback) {
DEBUG_ANDROID("android_java_callback: failed to get method id");
DEBUG_WARN("android_java_callback: failed to get method id");
goto finish;
}
(*env)->CallStaticVoidMethodV(env, jObjClass, jCallback, args);
finish:
if(attached == JNI_TRUE)
jni_detach_thread();
}
@ -134,6 +142,7 @@ jboolean java_callback_bool(jobject obj, const char * callback, const char* sign
jclass jObjClass;
jmethodID jCallback;
jboolean attached;
jboolean res = JNI_FALSE;
JNIEnv *env;
DEBUG_ANDROID("java_callback: %s (%s)", callback, signature);
@ -143,17 +152,20 @@ jboolean java_callback_bool(jobject obj, const char * callback, const char* sign
jObjClass = (*env)->GetObjectClass(env, obj);
if (!jObjClass) {
DEBUG_ANDROID("android_java_callback: failed to get class reference");
DEBUG_WARN("android_java_callback: failed to get class reference");
goto finish;
}
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
if (!jCallback) {
DEBUG_ANDROID("android_java_callback: failed to get method id");
DEBUG_WARN("android_java_callback: failed to get method id");
goto finish;
}
jboolean res = (*env)->CallStaticBooleanMethodV(env, jObjClass, jCallback, args);
res = (*env)->CallStaticBooleanMethodV(env, jObjClass, jCallback, args);
finish:
if(attached == JNI_TRUE)
jni_detach_thread();

View File

@ -9,6 +9,7 @@
package com.freerdp.freerdpcore.presentation;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@ -530,7 +531,15 @@ public class SessionActivity extends Activity
protected void onDestroy() {
super.onDestroy();
Log.v(TAG, "Session.onDestroy");
// Cancel running disconnect timers.
GlobalApp.cancelDisconnectTimer();
// Disconnect all remaining sessions.
Collection<SessionState> sessions = GlobalApp.getSessions();
for (SessionState session : sessions)
LibFreeRDP.disconnect(session.getInstance());
// unregister freerdp events broadcast receiver
unregisterReceiver(libFreeRDPBroadcastReceiver);

View File

@ -6,6 +6,60 @@
<project>FreeRDPCore</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>?children?</key>
<value>?name?=outputEntries\|?children?=?name?=entry\\\\\\\|\\\|?name?=entry\\\\\\\|\\\|\||</value>
</dictionary>
<dictionary>
<key>?name?</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>
<value>ndk-build</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.contents</key>
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>true</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
@ -26,9 +80,19 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>

View File

@ -3,14 +3,23 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
package="com.freerdp.afreerdp"
android:versionCode="3"
android:versionCode="@ANDROID_APP_VERSION@"
android:versionName="@GIT_REVISION@" >
<uses-sdk android:targetSdkVersion="@ANDROID_APP_TARGET_SDK@" android:minSdkVersion="@ANDROID_APP_MIN_SDK@"/>
<supports-screens android:anyDensity="true" android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" />
<uses-sdk
android:targetSdkVersion="@ANDROID_APP_TARGET_SDK@"
android:minSdkVersion="@ANDROID_APP_MIN_SDK@"/>
<supports-screens
android:anyDensity="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true" />
<application android:name="com.freerdp.afreerdp.application.GlobalApp"
android:label="aFreeRDP"
android:debuggable="@ANDROID_DEBUG_ENABLE@"
android:icon="@drawable/icon_launcher_freerdp" >
<!-- Main activity -->

View File

@ -18,6 +18,8 @@
set(ANDROID_PACKAGE_NAME "aFreeRDP")
add_subdirectory(jni)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake
${CMAKE_CURRENT_BINARY_DIR}/AndroidManifest.xml @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build.xml.cmake
@ -35,48 +37,30 @@ if (ANDROID_SDK)
${CMAKE_CURRENT_BINARY_DIR}/local.properties @ONLY)
endif()
if("${ANDROID_DEBUG_ENABLE}" STREQUAL "true")
# 1. generate Android.mk
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/jni/Android.mk
"APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
# 2. generate gdb.setup
get_directory_property(INCLUDE_DIRECTORIES DIRECTORY . INCLUDE_DIRECTORIES)
string(REGEX REPLACE ";" " " INCLUDE_DIRECTORIES "${INCLUDE_DIRECTORIES}")
set(LIB_DIRECTORIES "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}")
file(WRITE ${ANDROID_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/gdb.setup
"set solib-search-path ${CMAKE_CURRENT_BINARY_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}\n")
file(APPEND ${ANDROID_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/gdb.setup
"directory ${INCLUDE_DIRECTORIES} ${LIB_DIRECTORIES}\n")
# 3. copy gdbserver executable
file(COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver
DESTINATION ${ANDROID_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/)
# 4. Convenience target to launch debugger.
add_custom_target(debug-ndk
COMMAND adb install -r bin/aFreeRDP-debug.apk
COMMAND ndk-gdb --start --verbose --force
WORKING_DIRECTORY ${CURRENT_BINARY_DIR}
)
endif()
# command to create the android package
add_custom_target( ndk-build ALL
COMMAND ${NDK_COMMAND} NDK_DEBUG=${NDK_DEBUG}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPENDS freerdp-android
)
if(ANDROID_BUILD_JAVA)
if(NOT ANDROID_BUILD_JAVA_DEBUG)
set(APK "${ANDROID_BINARY_DIR}/bin/${ANDROID_PACKAGE_NAME}-release-unsigned.apk")
set(APK "${CMAKE_CURRENT_BINARY_DIR}/bin/${ANDROID_PACKAGE_NAME}-release-unsigned.apk")
else()
set(APK "${ANDROID_BINARY_DIR}/bin/${ANDROID_PACKAGE_NAME}-debug.apk")
set(APK "${CMAKE_CURRENT_BINARY_DIR}/bin/${ANDROID_PACKAGE_NAME}-debug.apk")
endif()
# command to create the android package
add_custom_command(
OUTPUT "${APK}"
COMMAND ${ANT_COMMAND} ${ANDROID_BUILD_TYPE}
WORKING_DIRECTORY "${ANDROID_BINARY_DIR}"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
MAIN_DEPENDENCY AndroidManifest.xml
DEPENDS freerdp-android
DEPENDS ndk-build
${CMAKE_CURRENT_BINARY_DIR}/local.properties
)
add_custom_target(android-package ALL SOURCES "${APK}")
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin")
endif()
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin;obj;libs")

View File

@ -0,0 +1 @@
include @NDK_LIB_CFG@

View File

@ -0,0 +1 @@
APP_ABI := @ANDROID_ABI@

View File

@ -0,0 +1,22 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# Android Client
#
# Copyright 2013 Armin Novak <anovak@thinstuff.at>
#
# 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.
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Application.mk.cmake
${CMAKE_CURRENT_BINARY_DIR}/Application.mk @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/Android.mk.cmake
${CMAKE_CURRENT_BINARY_DIR}/Android.mk @ONLY)

View File

@ -989,7 +989,7 @@ BOOL freerdp_client_detect_command_line(int argc, char** argv, DWORD* flags)
*flags |= COMMAND_LINE_SIGIL_DASH | COMMAND_LINE_SIGIL_DOUBLE_DASH;
*flags |= COMMAND_LINE_SIGIL_ENABLE_DISABLE;
if (windows_cli_count > posix_cli_count)
if (windows_cli_count >= posix_cli_count)
{
*flags = COMMAND_LINE_SEPARATOR_COLON;
*flags |= COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SIGIL_PLUS_MINUS;
@ -1098,7 +1098,6 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
return status;
}
arg = CommandLineFindArgumentA(args, "v");
arg = args;

View File

@ -199,7 +199,12 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
{
return -1;
}
freerdp_client_old_parse_hostname((char*) argv[index], &settings->ServerHostname, &settings->ServerPort);
if (settings)
{
freerdp_client_old_parse_hostname((char*) argv[index],
&settings->ServerHostname, &settings->ServerPort);
}
}
else
{
@ -280,14 +285,19 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
index++;
i++;
}
} else {
}
else
{
if (settings)
{
if (settings->instance)
{
freerdp_client_old_process_plugin(settings, args);
}
}
}
for (i=0; i<args->argc; i++)
for (i = 0; i < args->argc; i++)
free(args->argv[i]);
free(args->argv);
free(args);

View File

@ -976,7 +976,11 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
if (file->argc > 1)
{
char* ConnectionFile = settings->ConnectionFile;
settings->ConnectionFile = NULL;
freerdp_client_settings_parse_command_line(settings, file->argc, file->argv);
settings->ConnectionFile = ConnectionFile;
}
return TRUE;

View File

@ -25,7 +25,8 @@ option(WITH_ANDROID_DEBUG_MENU "Enable debug output for android jni bindings" ${
option(WITH_OPENSLES "Enable sound and microphone redirection using OpenSLES" ON)
option(ANDROID_BUILD_JAVA "Automatically android java code - build type depends on CMAKE_BUILD_TYPE" ON)
option(ANDROID_BUILD_JAVA_DEBUG "Create a android debug package" ${JAVA_DEBUG_DEFAULT})
set(ANDROID_APP_VERSION 3 CACHE STRING "Application version")
set(ANDROID_APP_TARGET_SDK 11 CACHE STRING "Application target android SDK")
set(ANDROID_APP_MIN_SDK 9 CACHE STRING "Application minimum android SDK requirement")
set(ANDROID_APP_GOOGLE_TARGET_SDK "16" CACHE STRING "Application target google SDK")

View File

@ -52,7 +52,8 @@ to the absolut paths on your machine:
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/AndroidToolchain.cmake \
-DANDROID_NDK="_your_ndk_path_here_" \
-DFREERDP_ANDROID_EXTERNAL_SSL_PATH="_your_ssl_build_root_path_" \
-DANDROID_SDK="_your_sdk_path_here_"
-DANDROID_SDK="_your_sdk_path_here_" \
-DCMAKE_BUILD_TYPE=Debug
make
After that you should have a client/Android/bin/aFreeRDP-debug.apk.
@ -66,12 +67,13 @@ to the absolut paths on your machine:
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/AndroidToolchain.cmake \
-DANDROID_NDK="_your_ndk_path_here_" \
-DFREERDP_ANDROID_EXTERNAL_SSL_PATH="_your_ssl_build_root_path_" \
-DANDROID_SDK="_your_sdk_path_here_" -DANDROID_BUILD_JAVA=OFF
-DANDROID_SDK="_your_sdk_path_here_" -DANDROID_BUILD_JAVA=OFF \
-DCMAKE_BUILD_TYPE=Debug
make
Now you can run your favourite ant command in client/Android like this:
cd client/Android
cd client/Android/aFreeRDP
ant debug install
Using an IDE
@ -83,7 +85,7 @@ the eclipse marketplace).
cmake -DCMAKE_TOOLCHAIN_FILE=cmake/AndroidToolchain.cmake \
-DANDROID_NDK="_your_ndk_path_here_" \
-DFREERDP_ANDROID_EXTERNAL_SSL_PATH="_your_ssl_build_root_path_" \
-DANDROID_BUILD_JAVA=OFF
-DCMAKE_BUILD_TYPE=Debug -DANDROID_BUILD_JAVA=OFF
make
Open Eclipse and choose:
@ -97,6 +99,14 @@ Side note: If you add -G "Eclipse CDT4 - Unix Makefiles" when running cmake
you can also import FreeRDP into Eclipse too. Then you have one Java project and one c/c++
project you can work on. This requires CDT to be installed in Eclipse.
Debugging native code
---------------------
All CMake builds created with -DCMAKE_BUILD_TYPE=Debug will be ready to
debug with ndk-gdb.
Eclipse projects are already configured to allow debugging in either Java
or native code, no extra steps required.
cmake variables
===============
@ -133,6 +143,35 @@ ANDROID_BUILD_JAVA (used by client/Android/CMakeLists.txt)
ANDROID_SDK (used by client/Android/CMakeLists.txt)
* absolute path to the Android SDK to use
ANDROID_NDK
* absolute path to the Android NDK to use.
WITH_DEBUG_ANDROID_JNI
* enable logcat debug messages for JNI calls.
WITH_ANDROID_DEBUG_MENU
* activate a debug menu in aFreeRDP to enable / disable runtime settings
* not available in release.
WITH_OPENSLES
* Enables / disables sound and microphone support for android using OpenSLES
ANDROID_BUILD_JAVA_DEBUG
* Enable / disable debugging code in the java parts of the application.
ANDROID_APP_VERSION
* The version the aFreeRDP-release.apk / aFreeRDP-debug.apk will have.
ANDROID_APP_TARGET_SDK
* The target SDK version of the project.
ANDROID_APP_MIN_SDK
* The lowest supported SDK version
ANDROID_NATIVE_API_LEVEL
* The native API level to compile the native code against.
* Should be equal to SDK level.
This is used to generate local.properties needed by ant. Needs to be set
if you build manually with ant or do integrated builds.

View File

@ -20,17 +20,46 @@
#ifndef FREERDP_UTILS_DEBUG_H
#define FREERDP_UTILS_DEBUG_H
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define DEBUG_NULL(fmt, ...) do { } while (0)
/* When building for android redirect all debug messages
* to logcat. */
#if defined(ANDROID)
#include <android/log.h>
#define APP_NAME "freerdp-debug"
#define ANDROID_DEBUG_PRINT(_dbg_str, fmt, ...) do { \
__android_log_print(_dbg_str, fmt, ##__VA_ARGS__); \
} while( 0 )
#define DEBUG_CLASS(_dbg_class, fmt, ...) \
ANDROID_DEBUG_PRINT(ANDROID_LOG_DEBUG, APP_NAME, \
"DBG_" #_dbg_class " %s (%s:%d): " \
fmt, __FUNCTION__, __FILE__, __LINE__, ## __VA_ARGS__)
#define DEBUG_WARN(fmt, ...) \
ANDROID_DEBUG_PRINT(ANDROID_LOG_WARN, APP_NAME, "Warning %s (%s:%d): " \
fmt, __FUNCTION__, __FILE__, __LINE__, ## __VA_ARGS__)
#else
/* By default all log messages are written to stdout */
#include <stdio.h>
#define DEBUG_PRINT(_dbg_str, fmt, ...) do { \
fprintf(stderr, _dbg_str, __FUNCTION__, __FILE__, __LINE__); \
fprintf(stderr, fmt, ## __VA_ARGS__); \
fprintf(stderr, "\n"); \
} while( 0 )
fprintf(stderr, _dbg_str, __FUNCTION__, __FILE__, __LINE__); \
fprintf(stderr, fmt, ## __VA_ARGS__); \
fprintf(stderr, "\n"); \
} while( 0 )
#define DEBUG_CLASS(_dbg_class, fmt, ...) DEBUG_PRINT("DBG_" #_dbg_class " %s (%s:%d): ", fmt, ## __VA_ARGS__)
#define DEBUG_WARN(fmt, ...) DEBUG_PRINT("Warning %s (%s:%d): ", fmt, ## __VA_ARGS__)
#endif
#ifdef WITH_DEBUG
#define DEBUG_MSG(fmt, ...) DEBUG_PRINT("DBG %s (%s:%d): ", fmt, ## __VA_ARGS__)

View File

@ -65,3 +65,7 @@ if(MONOLITHIC_BUILD)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
endif()
set(FREERDP_PC_LIBS "-lfreerdp -lwinpr")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp.pc.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

View File

@ -208,6 +208,10 @@ BOOL freerdp_check_fds(freerdp* instance)
int status;
rdpRdp* rdp;
assert(instance);
assert(instance->context);
assert(instance->context->rdp);
rdp = instance->context->rdp;
status = rdp_check_fds(rdp);

View File

@ -486,8 +486,15 @@ int input_process_events(rdpInput* input)
return input_message_queue_process_pending_messages(input);
}
static void input_free_queued_message(void *obj)
{
wMessage *msg = (wMessage*)obj;
input_message_queue_free_message(msg);
}
rdpInput* input_new(rdpRdp* rdp)
{
const wObject cb = { .fnObjectFree = input_free_queued_message };
rdpInput* input;
input = (rdpInput*) malloc(sizeof(rdpInput));
@ -496,7 +503,7 @@ rdpInput* input_new(rdpRdp* rdp)
{
ZeroMemory(input, sizeof(rdpInput));
input->queue = MessageQueue_New();
input->queue = MessageQueue_New(&cb);
}
return input;

File diff suppressed because it is too large Load Diff

View File

@ -123,6 +123,8 @@ struct rdp_update_proxy
};
int update_message_queue_process_message(rdpUpdate* update, wMessage* message);
int update_message_queue_free_message(wMessage* message);
int update_message_queue_process_pending_messages(rdpUpdate* update);
rdpUpdateProxy* update_message_proxy_new(rdpUpdate* update);
@ -148,6 +150,7 @@ struct rdp_input_proxy
};
int input_message_queue_process_message(rdpInput* input, wMessage* message);
int input_message_queue_free_message(wMessage* message);
int input_message_queue_process_pending_messages(rdpInput* input);
rdpInputProxy* input_message_proxy_new(rdpInput* input);

View File

@ -121,11 +121,11 @@ void tpdu_write_header(wStream* s, UINT16 length, BYTE code)
* @return length indicator (LI)
*/
BOOL tpdu_read_connection_request(wStream* s, BYTE *li)
BOOL tpdu_read_connection_request(wStream* s, BYTE* li)
{
BYTE code;
if(!tpdu_read_header(s, &code, li))
if (!tpdu_read_header(s, &code, li))
return FALSE;
if (code != X224_TPDU_CONNECTION_REQUEST)
@ -154,11 +154,11 @@ void tpdu_write_connection_request(wStream* s, UINT16 length)
* @return length indicator (LI)
*/
BOOL tpdu_read_connection_confirm(wStream* s, BYTE *li)
BOOL tpdu_read_connection_confirm(wStream* s, BYTE* li)
{
BYTE code;
if(!tpdu_read_header(s, &code, li))
if (!tpdu_read_header(s, &code, li))
return FALSE;
if (code != X224_TPDU_CONNECTION_CONFIRM)

View File

@ -41,14 +41,14 @@ enum X224_TPDU_TYPE
#define TPDU_CONNECTION_CONFIRM_LENGTH (TPKT_HEADER_LENGTH + TPDU_CONNECTION_CONFIRM_HEADER_LENGTH)
#define TPDU_DISCONNECT_REQUEST_LENGTH (TPKT_HEADER_LENGTH + TPDU_DISCONNECT_REQUEST_HEADER_LENGTH)
BOOL tpdu_read_header(wStream* s, BYTE* code, BYTE *li);
BOOL tpdu_read_header(wStream* s, BYTE* code, BYTE* li);
void tpdu_write_header(wStream* s, UINT16 length, BYTE code);
BOOL tpdu_read_connection_request(wStream* s, BYTE *li);
BOOL tpdu_read_connection_request(wStream* s, BYTE* li);
void tpdu_write_connection_request(wStream* s, UINT16 length);
BOOL tpdu_read_connection_confirm(wStream* s, BYTE *li);
BOOL tpdu_read_connection_confirm(wStream* s, BYTE* li);
void tpdu_write_connection_confirm(wStream* s, UINT16 length);
void tpdu_write_disconnect_request(wStream* s, UINT16 length);
BOOL tpdu_read_data(wStream* s, UINT16 *li);
BOOL tpdu_read_data(wStream* s, UINT16* li);
void tpdu_write_data(wStream* s);
#endif /* __TPDU_H */

View File

@ -573,7 +573,7 @@ int transport_read(rdpTransport* transport, wStream* s)
position += status;
}
Stream_Peek(s, header, 4); /* peek at first 4 bytes */
CopyMemory(header, Stream_Buffer(s), 4); /* peek at first 4 bytes */
/* if header is present, read in exactly one PDU */
if (header[0] == 0x03)
@ -1057,6 +1057,12 @@ void transport_free(rdpTransport* transport)
{
if (transport)
{
if (transport->async)
{
assert(!transport->thread);
assert(!transport->stopEvent);
}
if (transport->ReceiveBuffer)
Stream_Release(transport->ReceiveBuffer);

View File

@ -1544,8 +1544,16 @@ int update_process_messages(rdpUpdate* update)
return update_message_queue_process_pending_messages(update);
}
static void update_free_queued_message(void *obj)
{
wMessage *msg = (wMessage*)obj;
update_message_queue_free_message(msg);
}
rdpUpdate* update_new(rdpRdp* rdp)
{
const wObject cb = { .fnObjectFree = update_free_queued_message };
rdpUpdate* update;
update = (rdpUpdate*) malloc(sizeof(rdpUpdate));
@ -1587,7 +1595,7 @@ rdpUpdate* update_new(rdpRdp* rdp)
update->initialState = TRUE;
update->queue = MessageQueue_New();
update->queue = MessageQueue_New(&cb);
}
return update;

View File

@ -2,12 +2,12 @@ prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_PREFIX@/include
libs=@FREERDP_PC_LIBS@
Name: FreeRDP
Description: A free remote desktop protocol client
Description: FreeRDP: A Remote Desktop Protocol Implementation
URL: http://www.freerdp.com/
Version: @FREERDP_VERSION_FULL@
Requires:
Libs: -L${libdir} -lfreerdp-cache -lfreerdp-codec -lfreerdp-core -lfreerdp-crypto -lfreerdp-gdi -lfreerdp-locale -lfreerdp-rail -lfreerdp-utils -lwinpr-sspi -lwinpr-rpc -lwinpr-utils
Libs: -L${libdir} ${libs}
Cflags: -I${includedir}

View File

@ -1,6 +1,6 @@
#!/bin/bash
cd client/Android/FreeRDPCore/jni/generated/
cd @CMAKE_SOURCE_DIR@/client/Android/FreeRDPCore/jni/generated/
javah -classpath ../../bin/classes:@ANDROID_SDK@/platforms/android-8/android.jar -jni com.freerdp.freerdpcore.services.LibFreeRDP
rm com_freerdp_freerdpcore_services_LibFreeRDP_EventListener.h \
com_freerdp_freerdpcore_services_LibFreeRDP_UIEventListener.h

View File

@ -53,7 +53,7 @@
#define COMMAND_LINE_SIGIL_DOUBLE_DASH 0x00000008
#define COMMAND_LINE_SIGIL_PLUS_MINUS 0x00000010
#define COMMAND_LINE_SIGIL_ENABLE_DISABLE 0x00000020
#define COMMAND_LINE_SIGIL_NOT_ESCAPED 0x00000040
#define COMMAND_LINE_SIGIL_NOT_ESCAPED 0x00000040
#define COMMAND_LINE_SEPARATOR_COLON 0x00000100
#define COMMAND_LINE_SEPARATOR_EQUAL 0x00000200

View File

@ -402,6 +402,8 @@ struct _wMessageQueue
wMessage* array;
CRITICAL_SECTION lock;
HANDLE event;
wObject object;
};
typedef struct _wMessageQueue wMessageQueue;
@ -418,7 +420,43 @@ WINPR_API void MessageQueue_PostQuit(wMessageQueue* queue, int nExitCode);
WINPR_API int MessageQueue_Get(wMessageQueue* queue, wMessage* message);
WINPR_API int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL remove);
WINPR_API wMessageQueue* MessageQueue_New(void);
/*! \brief Clears all elements in a message queue.
*
* \note If dynamically allocated data is part of the messages,
* a custom cleanup handler must be passed in the 'callback'
* argument for MessageQueue_New.
*
* \param queue The queue to clear.
*
* \return 0 in case of success or a error code otherwise.
*/
WINPR_API int MessageQueue_Clear(wMessageQueue *queue);
/*! \brief Creates a new message queue.
* If 'callback' is null, no custom cleanup will be done
* on message queue deallocation.
* If the 'callback' argument contains valid uninit or
* free functions those will be called by
* 'MessageQueue_Clear'.
*
* \param callback a pointer to custom initialization / cleanup functions.
* Can be NULL if not used.
*
* \return A pointer to a newly allocated MessageQueue or NULL.
*/
WINPR_API wMessageQueue* MessageQueue_New(const wObject *callback);
/*! \brief Frees resources allocated by a message queue.
* This function will only free resources allocated
* internally.
*
* \note Empty the queue before calling this function with
* 'MessageQueue_Clear', 'MessageQueue_Get' or
* 'MessageQueue_Peek' to free all resources allocated
* by the message contained.
*
* \param queue A pointer to the queue to be freed.
*/
WINPR_API void MessageQueue_Free(wMessageQueue* queue);
/* Message Pipe */

View File

@ -242,14 +242,19 @@ WINPR_API HRESULT NativePathAllocCombineW(PCWSTR pszPathIn, PCWSTR pszMore, unsi
WINPR_API HRESULT PathCchConvertStyleA(PSTR pszPath, size_t cchPath, unsigned long dwFlags);
WINPR_API HRESULT PathCchConvertStyleW(PWSTR pszPath, size_t cchPath, unsigned long dwFlags);
WINPR_API char PathGetSeparatorA(unsigned long dwFlags);
WINPR_API WCHAR PathGetSeparatorW(unsigned long dwFlags);
WINPR_API PCSTR PathGetSharedLibraryExtensionA(unsigned long dwFlags);
WINPR_API PCWSTR PathGetSharedLibraryExtensionW(unsigned long dwFlags);
#ifdef UNICODE
#define PathCchConvertStyle PathCchConvertStyleW
#define PathGetSeparator PathGetSeparatorW
#define PathGetSharedLibraryExtension PathGetSharedLibraryExtensionW
#else
#define PathCchConvertStyle PathCchConvertStyleA
#define PathGetSeparator PathGetSeparatorW
#define PathGetSharedLibraryExtension PathGetSharedLibraryExtensionA
#endif
@ -276,7 +281,7 @@ extern "C" {
WINPR_API char* GetKnownPath(int id);
WINPR_API char* GetKnownSubPath(int id, char* path);
WINPR_API char* GetCombinedPath(char* basePath, char* subPath);
WINPR_API char* GetCombinedPath(const char* basePath, const char* subPath);
//#ifndef _WIN32

View File

@ -53,9 +53,25 @@ if(MONOLITHIC_BUILD)
set_target_properties(${MODULE_NAME} PROPERTIES LINKER_LANGUAGE C)
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib")
list(REMOVE_DUPLICATES WINPR_LIBS)
target_link_libraries(${MODULE_NAME} ${WINPR_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries EXPORT WinPRTargets)
set(WINPR_PC_LIBS "-lwinpr")
foreach(WINPR_LIB ${WINPR_LIBS})
if(${WINPR_LIB} MATCHES "^-l.*")
set(WINPR_PC_LIBS "${WINPR_PC_LIBS} ${WINPR_LIB}")
elseif(${WINPR_LIB} MATCHES "^/.*")
else()
set(WINPR_PC_LIBS "${WINPR_PC_LIBS} -l${WINPR_LIB}")
endif()
endforeach()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/winpr.pc.in ${CMAKE_CURRENT_BINARY_DIR}/winpr.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/winpr.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/libwinpr")
endif()

View File

@ -70,6 +70,10 @@
#include <sys/types.h>
#include <sys/stat.h>
#ifdef __MACOSX__
#include <mach-o/dyld.h>
#endif
DLL_DIRECTORY_COOKIE AddDllDirectory(PCWSTR NewDirectory)
{
return NULL;
@ -166,8 +170,8 @@ DWORD GetModuleFileNameW(HMODULE hModule, LPWSTR lpFilename, DWORD nSize)
}
DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize)
{
#ifdef __linux__
{
#if defined(__linux__)
int status;
int length;
char path[64];
@ -198,6 +202,46 @@ DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize)
lpFilename[nSize - 1] = '\0';
}
return 0;
}
#elif defined(__MACOSX__)
int status;
int length;
if (!hModule)
{
char path[4096];
char buffer[4096];
uint32_t size = sizeof(path);
status = _NSGetExecutablePath(path, &size);
if (status != 0)
{
/* path too small */
return 0;
}
/*
* _NSGetExecutablePath may not return the canonical path,
* so use realpath to find the absolute, canonical path.
*/
realpath(path, buffer);
length = strlen(buffer);
if (length < nSize)
{
CopyMemory(lpFilename, buffer, length);
lpFilename[length] = '\0';
}
else
{
CopyMemory(lpFilename, buffer, nSize - 1);
lpFilename[nSize - 1] = '\0';
}
return 0;
}
#endif

View File

@ -829,6 +829,44 @@ HRESULT PathCchConvertStyleW(PWSTR pszPath, size_t cchPath, unsigned long dwFlag
return S_OK;
}
/**
* PathGetSeparator
*/
char PathGetSeparatorA(unsigned long dwFlags)
{
char separator = PATH_SEPARATOR_CHR;
if (!dwFlags)
dwFlags = PATH_STYLE_NATIVE;
if (dwFlags == PATH_STYLE_WINDOWS)
separator = PATH_SEPARATOR_CHR;
else if (dwFlags == PATH_STYLE_UNIX)
separator = PATH_SEPARATOR_CHR;
else if (dwFlags == PATH_STYLE_NATIVE)
separator = PATH_SEPARATOR_CHR;
return separator;
}
WCHAR PathGetSeparatorW(unsigned long dwFlags)
{
WCHAR separator = PATH_SEPARATOR_CHR;
if (!dwFlags)
dwFlags = PATH_STYLE_NATIVE;
if (dwFlags == PATH_STYLE_WINDOWS)
separator = PATH_SEPARATOR_CHR;
else if (dwFlags == PATH_STYLE_UNIX)
separator = PATH_SEPARATOR_CHR;
else if (dwFlags == PATH_STYLE_NATIVE)
separator = PATH_SEPARATOR_CHR;
return separator;
}
/**
* PathGetSharedLibraryExtension
*/

View File

@ -271,7 +271,7 @@ char* GetKnownSubPath(int id, char* path)
return subPath;
}
char* GetCombinedPath(char* basePath, char* subPath)
char* GetCombinedPath(const char* basePath, const char* subPath)
{
int length;
HRESULT status;

View File

@ -66,7 +66,6 @@
#include <grp.h>
#include <errno.h>
#include <spawn.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>

View File

@ -54,8 +54,8 @@ wMessagePipe* MessagePipe_New()
if (pipe)
{
pipe->In = MessageQueue_New();
pipe->Out = MessageQueue_New();
pipe->In = MessageQueue_New(NULL);
pipe->Out = MessageQueue_New(NULL);
}
return pipe;

View File

@ -178,7 +178,7 @@ int MessageQueue_Peek(wMessageQueue* queue, wMessage* message, BOOL remove)
* Construction, Destruction
*/
wMessageQueue* MessageQueue_New()
wMessageQueue* MessageQueue_New(const wObject *callback)
{
wMessageQueue* queue = NULL;
@ -196,6 +196,11 @@ wMessageQueue* MessageQueue_New()
InitializeCriticalSectionAndSpinCount(&queue->lock, 4000);
queue->event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (callback)
queue->object = *callback;
else
ZeroMemory(&queue->object, sizeof(queue->object));
}
return queue;
@ -209,3 +214,32 @@ void MessageQueue_Free(wMessageQueue* queue)
free(queue->array);
free(queue);
}
int MessageQueue_Clear(wMessageQueue *queue)
{
int status = 0;
EnterCriticalSection(&queue->lock);
while(queue->size > 0)
{
wMessage *msg = &(queue->array[queue->head]);
/* Free resources of message. */
if (queue->object.fnObjectUninit)
queue->object.fnObjectUninit(msg);
if (queue->object.fnObjectFree)
queue->object.fnObjectFree(msg);
ZeroMemory(msg, sizeof(wMessage));
queue->head = (queue->head + 1) % queue->capacity;
queue->size--;
}
ResetEvent(queue->event);
LeaveCriticalSection(&queue->lock);
return status;
}

View File

@ -67,7 +67,7 @@ wStream* Stream_New(BYTE* buffer, size_t size)
s = malloc(sizeof(wStream));
if (s != NULL)
if (s)
{
if (buffer)
s->buffer = buffer;
@ -87,11 +87,11 @@ wStream* Stream_New(BYTE* buffer, size_t size)
void Stream_Free(wStream* s, BOOL bFreeBuffer)
{
if (s != NULL)
if (s)
{
if (bFreeBuffer)
{
if (s->buffer != NULL)
if (s->buffer)
free(s->buffer);
}

View File

@ -29,7 +29,7 @@ int TestMessageQueue(int argc, char* argv[])
HANDLE thread;
wMessageQueue* queue;
queue = MessageQueue_New();
queue = MessageQueue_New(NULL);
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) message_queue_consumer_thread, (void*) queue, 0, NULL);

View File

@ -0,0 +1,13 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_PREFIX@/include
libs=@WINPR_PC_LIBS@
Name: WinPR
Description: WinPR: Windows Portable Runtime
URL: http://www.freerdp.com/
Version: @WINPR_VERSION_FULL@
Requires:
Libs: -L${libdir} ${libs}
Cflags: -I${includedir}