diff --git a/CMakeLists.txt b/CMakeLists.txt
index edd2e0aa5..445e81fd3 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -329,8 +329,9 @@ if(APPLE)
set(DIRECTFB_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "OPTIONAL")
set(GSTREAMER_FEATURE_TYPE "OPTIONAL")
- set(X11_FEATURE_TYPE "DISABLED")
+ set(X11_FEATURE_TYPE "OPTIONAL")
if(IOS)
+ set(X11_FEATURE_TYPE "DISABLED")
set(ALSA_FEATURE_TYPE "DISABLED")
set(PULSE_FEATURE_TYPE "DISABLED")
set(CUPS_FEATURE_TYPE "DISABLED")
@@ -353,6 +354,11 @@ endif()
find_feature(X11 ${X11_FEATURE_TYPE} ${X11_FEATURE_PURPOSE} ${X11_FEATURE_DESCRIPTION})
find_feature(DirectFB ${DIRECTFB_FEATURE_TYPE} ${DIRECTFB_FEATURE_PURPOSE} ${DIRECTFB_FEATURE_DESCRIPTION})
+if (${WITH_DIRECTFB})
+ message(WARNING "
+DIRECTFB is orphaned and not maintained see docs/README.directfb for details
+")
+endif()
find_feature(ZLIB ${ZLIB_FEATURE_TYPE} ${ZLIB_FEATURE_PURPOSE} ${ZLIB_FEATURE_DESCRIPTION})
find_feature(OpenSSL ${OPENSSL_FEATURE_TYPE} ${OPENSSL_FEATURE_PURPOSE} ${OPENSSL_FEATURE_DESCRIPTION})
diff --git a/buildx/client/Mac/cli/Info.plist b/buildx/client/Mac/cli/Info.plist
deleted file mode 100644
index cb6976502..000000000
--- a/buildx/client/Mac/cli/Info.plist
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
-
- CFBundleIconFile
- FreeRDP
- CFBundleIdentifier
- FreeRDP.Mac
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
-
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- 1.0
- CFBundleSignature
- ????
- CFBundleVersion
- 1
- LSMinimumSystemVersion
-
- NSHumanReadableCopyright
- Copyright © 2012 __MyCompanyName__. All rights reserved.
- NSMainNibFile
- MainMenu
- NSPrincipalClass
- NSApplication
-
-
diff --git a/channels/client/channels.c b/channels/client/channels.c
index a9ea2b0dc..bf886dba4 100644
--- a/channels/client/channels.c
+++ b/channels/client/channels.c
@@ -441,10 +441,14 @@ int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, c
int freerdp_drdynvc_on_channel_connected(DrdynvcClientContext* context, const char* name, void* pInterface)
{
int status = 0;
+ ChannelConnectedEventArgs e;
rdpChannels* channels = (rdpChannels*) context->custom;
freerdp* instance = channels->instance;
- IFCALLRET(instance->OnChannelConnected, status, instance, name, pInterface);
+ EventArgsInit(&e, "freerdp");
+ e.name = name;
+ e.pInterface = pInterface;
+ PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e);
return status;
}
@@ -452,10 +456,14 @@ int freerdp_drdynvc_on_channel_connected(DrdynvcClientContext* context, const ch
int freerdp_drdynvc_on_channel_disconnected(DrdynvcClientContext* context, const char* name, void* pInterface)
{
int status = 0;
+ ChannelDisconnectedEventArgs e;
rdpChannels* channels = (rdpChannels*) context->custom;
freerdp* instance = channels->instance;
- IFCALLRET(instance->OnChannelDisconnected, status, instance, name, pInterface);
+ EventArgsInit(&e, "freerdp");
+ e.name = name;
+ e.pInterface = pInterface;
+ PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e);
return status;
}
diff --git a/channels/disp/CMakeLists.txt b/channels/disp/CMakeLists.txt
new file mode 100644
index 000000000..541892d95
--- /dev/null
+++ b/channels/disp/CMakeLists.txt
@@ -0,0 +1,22 @@
+# FreeRDP: A Remote Desktop Protocol Implementation
+# FreeRDP cmake build script
+#
+# Copyright 2012 Marc-Andre Moreau
+#
+# 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("disp")
+
+if(WITH_CLIENT_CHANNELS)
+ add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
+endif()
diff --git a/channels/disp/ChannelOptions.cmake b/channels/disp/ChannelOptions.cmake
new file mode 100644
index 000000000..0e254adad
--- /dev/null
+++ b/channels/disp/ChannelOptions.cmake
@@ -0,0 +1,12 @@
+
+set(OPTION_DEFAULT OFF)
+set(OPTION_CLIENT_DEFAULT ON)
+set(OPTION_SERVER_DEFAULT OFF)
+
+define_channel_options(NAME "disp" TYPE "dynamic"
+ DESCRIPTION "Display Update Virtual Channel Extension"
+ SPECIFICATIONS "[MS-RDPEDISP]"
+ DEFAULT ${OPTION_DEFAULT})
+
+define_channel_client_options(${OPTION_CLIENT_DEFAULT})
+define_channel_server_options(${OPTION_SERVER_DEFAULT})
diff --git a/channels/disp/client/CMakeLists.txt b/channels/disp/client/CMakeLists.txt
new file mode 100644
index 000000000..403a15ce4
--- /dev/null
+++ b/channels/disp/client/CMakeLists.txt
@@ -0,0 +1,47 @@
+# FreeRDP: A Remote Desktop Protocol Implementation
+# FreeRDP cmake build script
+#
+# Copyright 2013 Marc-Andre Moreau
+#
+# 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("disp")
+
+set(${MODULE_PREFIX}_SRCS
+ disp_main.c
+ disp_main.h)
+
+include_directories(..)
+
+add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
+
+set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
+
+set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
+ MONOLITHIC ${MONOLITHIC_BUILD}
+ MODULE freerdp
+ MODULES freerdp-common freerdp-utils)
+
+set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
+ MONOLITHIC ${MONOLITHIC_BUILD}
+ MODULE winpr
+ MODULES winpr-sysinfo)
+
+target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
+
+if(NOT STATIC_CHANNELS)
+ install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
+endif()
+
+set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
+
diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c
new file mode 100644
index 000000000..feb971550
--- /dev/null
+++ b/channels/disp/client/disp_main.c
@@ -0,0 +1,341 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Display Update Virtual Channel Extension
+ *
+ * Copyright 2013 Marc-Andre Moreau
+ *
+ * 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
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "disp_main.h"
+
+struct _DISP_CHANNEL_CALLBACK
+{
+ IWTSVirtualChannelCallback iface;
+
+ IWTSPlugin* plugin;
+ IWTSVirtualChannelManager* channel_mgr;
+ IWTSVirtualChannel* channel;
+};
+typedef struct _DISP_CHANNEL_CALLBACK DISP_CHANNEL_CALLBACK;
+
+struct _DISP_LISTENER_CALLBACK
+{
+ IWTSListenerCallback iface;
+
+ IWTSPlugin* plugin;
+ IWTSVirtualChannelManager* channel_mgr;
+ DISP_CHANNEL_CALLBACK* channel_callback;
+};
+typedef struct _DISP_LISTENER_CALLBACK DISP_LISTENER_CALLBACK;
+
+struct _DISP_PLUGIN
+{
+ IWTSPlugin iface;
+
+ IWTSListener* listener;
+ DISP_LISTENER_CALLBACK* listener_callback;
+
+ UINT32 MaxNumMonitors;
+ UINT32 MaxMonitorWidth;
+ UINT32 MaxMonitorHeight;
+};
+typedef struct _DISP_PLUGIN DISP_PLUGIN;
+
+int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors)
+{
+ int index;
+ int status;
+ wStream* s;
+ UINT32 type;
+ UINT32 length;
+ DISP_PLUGIN* disp;
+ UINT32 MonitorLayoutSize;
+
+ disp = (DISP_PLUGIN*) callback->plugin;
+
+#ifdef DISP_PREVIEW
+ MonitorLayoutSize = 32;
+#else
+ MonitorLayoutSize = 40;
+#endif
+
+ length = 8 + 8 + (NumMonitors * MonitorLayoutSize);
+
+ type = DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT;
+
+ s = Stream_New(NULL, length);
+
+ Stream_Write_UINT32(s, type); /* Type (4 bytes) */
+ Stream_Write_UINT32(s, length); /* Length (4 bytes) */
+
+ if (NumMonitors > disp->MaxNumMonitors)
+ NumMonitors = disp->MaxNumMonitors;
+
+#ifdef DISP_PREVIEW
+ Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */
+#else
+ Stream_Write_UINT32(s, MonitorLayoutSize); /* MonitorLayoutSize (4 bytes) */
+#endif
+
+ Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */
+
+ //fprintf(stderr, "NumMonitors: %d\n", NumMonitors);
+
+ for (index = 0; index < NumMonitors; index++)
+ {
+ Monitors[index].Width -= (Monitors[index].Width % 2);
+
+ if (Monitors[index].Width < 200)
+ Monitors[index].Width = 200;
+
+ if (Monitors[index].Width > disp->MaxMonitorWidth)
+ Monitors[index].Width = disp->MaxMonitorWidth;
+
+ if (Monitors[index].Height < 200)
+ Monitors[index].Height = 200;
+
+ if (Monitors[index].Height > disp->MaxMonitorHeight)
+ Monitors[index].Height = disp->MaxMonitorHeight;
+
+ Stream_Write_UINT32(s, Monitors[index].Flags); /* Flags (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].Left); /* Left (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].Top); /* Top (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].Width); /* Width (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].Height); /* Height (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].PhysicalWidth); /* PhysicalWidth (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].PhysicalHeight); /* PhysicalHeight (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].Orientation); /* Orientation (4 bytes) */
+
+#if 0
+ fprintf(stderr, "\t: Flags: 0x%04X\n", Monitors[index].Flags);
+ fprintf(stderr, "\t: Left: %d\n", Monitors[index].Left);
+ fprintf(stderr, "\t: Top: %d\n", Monitors[index].Top);
+ fprintf(stderr, "\t: Width: %d\n", Monitors[index].Width);
+ fprintf(stderr, "\t: Height: %d\n", Monitors[index].Height);
+ fprintf(stderr, "\t: PhysicalWidth: %d\n", Monitors[index].PhysicalWidth);
+ fprintf(stderr, "\t: PhysicalHeight: %d\n", Monitors[index].PhysicalHeight);
+ fprintf(stderr, "\t: Orientation: %d\n", Monitors[index].Orientation);
+#endif
+
+#ifndef DISP_PREVIEW
+ Stream_Write_UINT32(s, Monitors[index].DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */
+ Stream_Write_UINT32(s, Monitors[index].DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */
+#endif
+ }
+
+ Stream_SealLength(s);
+
+ status = callback->channel->Write(callback->channel, Stream_Length(s), Stream_Buffer(s), NULL);
+
+ Stream_Free(s, TRUE);
+
+ return status;
+}
+
+int disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s)
+{
+ DISP_PLUGIN* disp;
+
+ disp = (DISP_PLUGIN*) callback->plugin;
+
+ Stream_Read_UINT32(s, disp->MaxNumMonitors); /* MaxNumMonitors (4 bytes) */
+ Stream_Read_UINT32(s, disp->MaxMonitorWidth); /* MaxMonitorWidth (4 bytes) */
+ Stream_Read_UINT32(s, disp->MaxMonitorHeight); /* MaxMonitorHeight (4 bytes) */
+
+ //fprintf(stderr, "DisplayControlCapsPdu: MaxNumMonitors: %d MaxMonitorWidth: %d MaxMonitorHeight: %d\n",
+ // disp->MaxNumMonitors, disp->MaxMonitorWidth, disp->MaxMonitorHeight);
+
+ return 0;
+}
+
+int disp_recv_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s)
+{
+ UINT32 type;
+ UINT32 length;
+
+ Stream_Read_UINT32(s, type); /* Type (4 bytes) */
+ Stream_Read_UINT32(s, length); /* Length (4 bytes) */
+
+ //fprintf(stderr, "Type: %d Length: %d\n", type, length);
+
+ switch (type)
+ {
+ case DISPLAY_CONTROL_PDU_TYPE_CAPS:
+ disp_recv_display_control_caps_pdu(callback, s);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer)
+{
+ wStream* s;
+ int status = 0;
+ DISP_CHANNEL_CALLBACK* callback = (DISP_CHANNEL_CALLBACK*) pChannelCallback;
+
+ s = Stream_New(pBuffer, cbSize);
+
+ status = disp_recv_pdu(callback, s);
+
+ Stream_Free(s, FALSE);
+
+ return status;
+}
+
+static int disp_on_close(IWTSVirtualChannelCallback* pChannelCallback)
+{
+ DISP_CHANNEL_CALLBACK* callback = (DISP_CHANNEL_CALLBACK*) pChannelCallback;
+
+ if (callback)
+ {
+ free(callback);
+ }
+
+ return 0;
+}
+
+static int disp_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
+ IWTSVirtualChannel* pChannel, BYTE* Data, int* pbAccept,
+ IWTSVirtualChannelCallback** ppCallback)
+{
+ DISP_CHANNEL_CALLBACK* callback;
+ DISP_LISTENER_CALLBACK* listener_callback = (DISP_LISTENER_CALLBACK*) pListenerCallback;
+
+ callback = (DISP_CHANNEL_CALLBACK*) malloc(sizeof(DISP_CHANNEL_CALLBACK));
+ ZeroMemory(callback, sizeof(DISP_CHANNEL_CALLBACK));
+
+ callback->iface.OnDataReceived = disp_on_data_received;
+ callback->iface.OnClose = disp_on_close;
+ callback->plugin = listener_callback->plugin;
+ callback->channel_mgr = listener_callback->channel_mgr;
+ callback->channel = pChannel;
+ listener_callback->channel_callback = callback;
+
+ *ppCallback = (IWTSVirtualChannelCallback*) callback;
+
+ return 0;
+}
+
+static int disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
+{
+ int status;
+ DISP_PLUGIN* disp = (DISP_PLUGIN*) pPlugin;
+
+ disp->listener_callback = (DISP_LISTENER_CALLBACK*) malloc(sizeof(DISP_LISTENER_CALLBACK));
+ ZeroMemory(disp->listener_callback, sizeof(DISP_LISTENER_CALLBACK));
+
+ disp->listener_callback->iface.OnNewChannelConnection = disp_on_new_channel_connection;
+ disp->listener_callback->plugin = pPlugin;
+ disp->listener_callback->channel_mgr = pChannelMgr;
+
+ status = pChannelMgr->CreateListener(pChannelMgr, DISP_DVC_CHANNEL_NAME, 0,
+ (IWTSListenerCallback*) disp->listener_callback, &(disp->listener));
+
+ disp->listener->pInterface = disp->iface.pInterface;
+
+ return status;
+}
+
+static int disp_plugin_terminated(IWTSPlugin* pPlugin)
+{
+ DISP_PLUGIN* disp = (DISP_PLUGIN*) pPlugin;
+
+ if (disp)
+ {
+ free(disp);
+ }
+
+ return 0;
+}
+
+/**
+ * Channel Client Interface
+ */
+
+int disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors)
+{
+ DISP_PLUGIN* disp = (DISP_PLUGIN*) context->handle;
+ DISP_CHANNEL_CALLBACK* callback = disp->listener_callback->channel_callback;
+
+ disp_send_display_control_monitor_layout_pdu(callback, NumMonitors, Monitors);
+
+ return 1;
+}
+
+#ifdef STATIC_CHANNELS
+#define DVCPluginEntry disp_DVCPluginEntry
+#endif
+
+int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
+{
+ int error = 0;
+ DISP_PLUGIN* disp;
+ DispClientContext* context;
+
+ disp = (DISP_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "disp");
+
+ if (disp == NULL)
+ {
+ disp = (DISP_PLUGIN*) malloc(sizeof(DISP_PLUGIN));
+
+ if (disp)
+ {
+ ZeroMemory(disp, sizeof(DISP_PLUGIN));
+
+ disp->iface.Initialize = disp_plugin_initialize;
+ disp->iface.Connected = NULL;
+ disp->iface.Disconnected = NULL;
+ disp->iface.Terminated = disp_plugin_terminated;
+
+ context = (DispClientContext*) malloc(sizeof(DispClientContext));
+
+ context->handle = (void*) disp;
+
+ context->SendMonitorLayout = disp_send_monitor_layout;
+
+ disp->iface.pInterface = (void*) context;
+
+ disp->MaxNumMonitors = 16;
+ disp->MaxMonitorWidth = 8192;
+ disp->MaxMonitorHeight = 8192;
+
+ error = pEntryPoints->RegisterPlugin(pEntryPoints, "disp", (IWTSPlugin*) disp);
+ }
+ }
+
+ return error;
+}
diff --git a/channels/disp/client/disp_main.h b/channels/disp/client/disp_main.h
new file mode 100644
index 000000000..db1ce10c5
--- /dev/null
+++ b/channels/disp/client/disp_main.h
@@ -0,0 +1,40 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Display Update Virtual Channel Extension
+ *
+ * Copyright 2013 Marc-Andre Moreau
+ *
+ * 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_DISP_CLIENT_MAIN_H
+#define FREERDP_CHANNEL_DISP_CLIENT_MAIN_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
+#include
+#include
+
+#include
+
+#define DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT 0x00000002
+#define DISPLAY_CONTROL_PDU_TYPE_CAPS 0x00000003
+
+#define DISP_PREVIEW 1
+
+#endif /* FREERDP_CHANNEL_DISP_CLIENT_MAIN_H */
+
diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c
index ac897a669..954247d02 100644
--- a/channels/drdynvc/client/dvcman.c
+++ b/channels/drdynvc/client/dvcman.c
@@ -376,16 +376,13 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
{
DEBUG_WARN("channel rejected by plugin");
- channel->status = 1;
- ArrayList_Add(dvcman->channels, channel);
+ free(channel);
return 1;
}
}
}
- channel->status = 1;
- ArrayList_Add(dvcman->channels, channel);
-
+ free(channel);
return 1;
}
diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c
index 854fd46ab..3984b6c32 100644
--- a/channels/rdpei/client/rdpei_main.c
+++ b/channels/rdpei/client/rdpei_main.c
@@ -212,7 +212,7 @@ int rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback)
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
Stream_Write_UINT32(s, flags); /* flags (4 bytes) */
- Stream_Write_UINT32(s, RDPINPUT_PROTOCOL_V1); /* protocolVersion (4 bytes) */
+ Stream_Write_UINT32(s, RDPINPUT_PROTOCOL_V10); /* protocolVersion (4 bytes) */
Stream_Write_UINT16(s, rdpei->maxTouchContacts); /* maxTouchContacts (2 bytes) */
Stream_SealLength(s);
@@ -249,6 +249,7 @@ void rdpei_print_contact_flags(UINT32 contactFlags)
int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
{
int index;
+ int rectSize = 2;
RDPINPUT_CONTACT_DATA* contact;
#ifdef WITH_DEBUG_RDPEI
@@ -264,12 +265,18 @@ int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
*/
rdpei_write_8byte_unsigned(s, frame->frameOffset * 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */
- Stream_EnsureRemainingCapacity(s, frame->contactCount * 32);
+ Stream_EnsureRemainingCapacity(s, frame->contactCount * 64);
for (index = 0; index < frame->contactCount; index++)
{
contact = &frame->contacts[index];
+ contact->fieldsPresent |= CONTACT_DATA_CONTACTRECT_PRESENT;
+ contact->contactRectLeft = contact->x - rectSize;
+ contact->contactRectTop = contact->y - rectSize;
+ contact->contactRectRight = contact->x + rectSize;
+ contact->contactRectBottom = contact->y + rectSize;
+
#ifdef WITH_DEBUG_RDPEI
printf("contact[%d].contactId: %d\n", index, contact->contactId);
printf("contact[%d].fieldsPresent: %d\n", index, contact->fieldsPresent);
@@ -325,7 +332,7 @@ int rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH_
wStream* s;
UINT32 pduLength;
- pduLength = 64 + (frame->contactCount * 32);
+ pduLength = 64 + (frame->contactCount * 64);
s = Stream_New(NULL, pduLength);
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
@@ -355,11 +362,13 @@ int rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
Stream_Read_UINT32(s, protocolVersion); /* protocolVersion (4 bytes) */
- if (protocolVersion != RDPINPUT_PROTOCOL_V1)
+#if 0
+ if (protocolVersion != RDPINPUT_PROTOCOL_V10)
{
fprintf(stderr, "Unknown [MS-RDPEI] protocolVersion: 0x%08X\n", protocolVersion);
return -1;
}
+#endif
return 0;
}
diff --git a/channels/rdpei/client/rdpei_main.h b/channels/rdpei/client/rdpei_main.h
index c0d0d2d67..cf4dccee0 100644
--- a/channels/rdpei/client/rdpei_main.h
+++ b/channels/rdpei/client/rdpei_main.h
@@ -35,7 +35,8 @@
/* Protocol Version */
-#define RDPINPUT_PROTOCOL_V1 0x00010000
+#define RDPINPUT_PROTOCOL_V10 0x00010000
+#define RDPINPUT_PROTOCOL_V101 0x00010001
/* Client Ready Flags */
diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c
index df4700e9f..fb6b07915 100644
--- a/channels/serial/client/serial_main.c
+++ b/channels/serial/client/serial_main.c
@@ -67,7 +67,6 @@ struct _SERIAL_DEVICE
wQueue* queue;
LIST* pending_irps;
- HANDLE in_event;
fd_set read_fds;
fd_set write_fds;
@@ -330,7 +329,9 @@ static void* serial_thread_func(void* arg)
if (WaitForSingleObject(serial->stopEvent, 0) == WAIT_OBJECT_0)
break;
- if (WaitForSingleObject(Queue_Event(serial->queue), 10) == WAIT_OBJECT_0)
+ status = WaitForSingleObject(Queue_Event(serial->queue), 10);
+
+ if ((status != WAIT_OBJECT_0) && (status != WAIT_TIMEOUT))
break;
serial->nfds = 1;
@@ -341,18 +342,13 @@ static void* serial_thread_func(void* arg)
serial->tv.tv_usec = 0;
serial->select_timeout = 0;
- irp = (IRP*) Queue_Dequeue(serial->queue);
-
- if (irp)
- serial_process_irp(serial, irp);
-
- status = WaitForSingleObject(serial->in_event, 0);
-
- if ((status == WAIT_OBJECT_0) || (status == WAIT_TIMEOUT))
+ if (status == WAIT_OBJECT_0)
{
- if (serial_check_fds(serial))
- ResetEvent(serial->in_event);
+ if ((irp = (IRP*) Queue_Dequeue(serial->queue)))
+ serial_process_irp(serial, irp);
}
+
+ serial_check_fds(serial);
}
return NULL;
@@ -423,7 +419,6 @@ static void serial_abort_single_io(SERIAL_DEVICE* serial, UINT32 file_id, UINT32
Stream_Write_UINT32(irp->output, 0);
irp->Complete(irp);
- SetEvent(serial->in_event);
break;
}
@@ -460,8 +455,6 @@ static void serial_check_for_events(SERIAL_DEVICE* serial)
prev = irp;
irp = (IRP*) list_next(serial->pending_irps, irp);
list_remove(serial->pending_irps, prev);
-
- SetEvent(serial->in_event);
}
}
@@ -537,7 +530,6 @@ static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp)
irp->IoStatus = STATUS_PENDING;
list_enqueue(serial->pending_irps, irp);
- SetEvent(serial->in_event);
}
static void __serial_check_fds(SERIAL_DEVICE* serial)
@@ -599,10 +591,7 @@ static void __serial_check_fds(SERIAL_DEVICE* serial)
irp = (IRP*) list_next(serial->pending_irps, irp);
if (irp_completed || (prev->IoStatus == STATUS_SUCCESS))
- {
list_remove(serial->pending_irps, prev);
- SetEvent(serial->in_event);
- }
}
}
@@ -692,7 +681,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
name = device->Name;
path = device->Path;
- if (name[0] && path[0])
+ if ((name && name[0]) && (path && path[0]))
{
serial = (SERIAL_DEVICE*) malloc(sizeof(SERIAL_DEVICE));
ZeroMemory(serial, sizeof(SERIAL_DEVICE));
@@ -711,7 +700,6 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
serial->path = path;
serial->queue = Queue_New(TRUE, -1, -1);
serial->pending_irps = list_new();
- serial->in_event = CreateEvent(NULL, TRUE, FALSE, NULL);
serial->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
diff --git a/channels/server/CMakeLists.txt b/channels/server/CMakeLists.txt
index b86cd6df4..aa15ce965 100644
--- a/channels/server/CMakeLists.txt
+++ b/channels/server/CMakeLists.txt
@@ -40,7 +40,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
- MODULES winpr-crt winpr-synch winpr-interlocked)
+ MODULES winpr-crt winpr-synch winpr-interlocked winpr-error)
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} PARENT_SCOPE)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)
diff --git a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c
index 9e2c1674d..9ead22b81 100644
--- a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c
+++ b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c
@@ -669,7 +669,6 @@ static BOOL tsmf_gstreamer_set_format(ITSMFDecoder * decoder, TS_AM_MEDIA_TYPE *
return FALSE;
}
-
return TRUE;
}
@@ -1133,12 +1132,12 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
{
- DEBUG_DVC("tsmf_gstreamer_decodeEx_VIDEO. Start:(%llu) End:(%llu) Duration:(%llu) Last End:(%llu)",
+ DEBUG_DVC("tsmf_gstreamer_decodeEx_VIDEO. Start:(%"PRIu64") End:(%"PRIu64") Duration:(%"PRIu64") Last End:(%"PRIu64")",
start_time, end_time, duration, mdecoder->last_sample_end_time);
}
else
{
- DEBUG_DVC("tsmf_gstreamer_decodeEX_AUDIO. Start:(%llu) End:(%llu) Duration:(%llu) Last End:(%llu)",
+ DEBUG_DVC("tsmf_gstreamer_decodeEx_AUDIO. Start:(%"PRIu64") End:(%"PRIu64") Duration:(%"PRIu64") Last End:(%"PRIu64")",
start_time, end_time, duration, mdecoder->last_sample_end_time);
}
@@ -1176,7 +1175,7 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
*/
if (start_time > (mdecoder->last_sample_end_time + 10000000) || (end_time + 10000000) < mdecoder->last_sample_end_time)
{
- DEBUG_DVC("tsmf_gstreamer_decodeEx: start_time=[%llu] > last_sample_end_time=[%llu]", start_time, mdecoder->last_sample_end_time);
+ DEBUG_DVC("tsmf_gstreamer_decodeEx: start_time=[%"PRIu64"] > last_sample_end_time=[%"PRIu64"]", start_time, mdecoder->last_sample_end_time);
DEBUG_DVC("tsmf_gstreamer_decodeEx: Stream seek detected - flushing element.");
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
gst_object_unref(mdecoder->pipe);
@@ -1205,7 +1204,7 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
if (fout)
{
- fprintf(fout, "%"PRIu64"\n", (long unsigned int) start_time);
+ fprintf(fout, "%"PRIu64"\n", start_time);
fclose(fout);
}
@@ -1231,7 +1230,7 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
if (fin)
{
UINT64 AStartTime = 0;
- fscanf(fin, "%"PRIu64, (long unsigned int*) &AStartTime);
+ fscanf(fin, "%"PRIu64, &AStartTime);
fclose(fin);
if (start_time > AStartTime)
{
@@ -1265,7 +1264,7 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
if (fin)
{
UINT64 VStartTime = 0;
- fscanf(fin, "%"PRIu64, (long unsigned int*) &VStartTime);
+ fscanf(fin, "%"PRIu64, &VStartTime);
fclose(fin);
if (start_time > VStartTime)
{
@@ -1283,7 +1282,7 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, U
pthread_mutex_unlock(&mdecoder->gst_mutex);
DEBUG_WARN("tsmf_gstreamer_decodeEx: gst_buffer_try_new_and_alloc(%d) failed.", data_size);
return FALSE;
- }
+ }
gst_buffer_set_caps(gst_buf, mdecoder->gst_caps);
memcpy(GST_BUFFER_MALLOCDATA(gst_buf), data, data_size);
GST_BUFFER_TIMESTAMP(gst_buf) = tsmf_gstreamer_timestamp_ms_to_gst(start_time);
@@ -1325,20 +1324,21 @@ static void tsmf_gstreamer_change_volume(ITSMFDecoder * decoder, UINT32 newVolum
if (mdecoder->shutdown)
return;
- if (!mdecoder->aVolume)
+ if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
return;
- if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
+ mdecoder->gstMuted = (BOOL) muted;
+ DEBUG_DVC("tsmf_gstreamer_change_volume: mute=[%d]", mdecoder->gstMuted);
+ mdecoder->gstVolume = (double) newVolume / (double) 10000;
+ DEBUG_DVC("tsmf_gstreamer_change_volume: gst_new_vol=[%f]", mdecoder->gstVolume);
+
+ if (!mdecoder->aVolume)
return;
if (!G_IS_OBJECT(mdecoder->aVolume))
return;
- mdecoder->gstMuted = (BOOL) muted;
- DEBUG_DVC("tsmf_gstreamer_change_volume: mute=[%d]", mdecoder->gstMuted);
g_object_set(mdecoder->aVolume, "mute", mdecoder->gstMuted, NULL);
- mdecoder->gstVolume = (double) newVolume / (double) 10000;
- DEBUG_DVC("tsmf_gstreamer_change_volume: gst_new_vol=[%f]", mdecoder->gstVolume);
g_object_set(mdecoder->aVolume, "volume", mdecoder->gstVolume, NULL);
}
@@ -1482,7 +1482,7 @@ static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder * decoder)
GstFormat fmt = GST_FORMAT_TIME;
gint64 pos = 0;
gst_element_query_position (mdecoder->outsink, &fmt, &pos);
- DEBUG_DVC("tsmf_gstreamer_current_pos=[%llu]", pos);
+ DEBUG_DVC("tsmf_gstreamer_current_pos=[%"PRIu64"]", pos);
return pos/100;
}
@@ -1524,13 +1524,14 @@ static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder * decoder, int new
{
if (info->noutput > 0)
{
- if (info->outputs[0] == primary_output)
+ if (info->outputs[0] == primary_output || i == 0)
{
mdecoder->xOffset = info->x;
mdecoder->yOffset = info->y;
}
DEBUG_DVC("output %d ID: %lu (x,y): (%d,%d) (w,h): (%d,%d) primary: %d", i, info->outputs[0], info->x, info->y, info->width, info->height, (info->outputs[0] == primary_output));
}
+ XRRFreeCrtcInfo(info);
}
}
}
@@ -1545,7 +1546,12 @@ static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder * decoder, int new
if(mdecoder->subwin)
{
XMoveWindow(mdecoder->disp, mdecoder->subwin, anewX, anewY);
- XResizeWindow(mdecoder->disp, mdecoder->subwin, newWidth, newHeight);
+ if(newWidth > 0 && newHeight > 0) {
+ XResizeWindow(mdecoder->disp, mdecoder->subwin, newWidth, newHeight);
+ } else {
+ XResizeWindow(mdecoder->disp, mdecoder->subwin, 1, 1);
+ }
+
XSync(mdecoder->disp, FALSE);
XShapeCombineRectangles (mdecoder->disp, mdecoder->subwin, ShapeBounding, 0, 0,(XRectangle*) rectangles, numRectangles, ShapeSet, Unsorted);
XSync(mdecoder->disp, FALSE);
@@ -1599,7 +1605,7 @@ ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
decoder->xOffset = 0;
decoder->yOffset = 0;
decoder->offsetObtained = FALSE;
- decoder->gstVolume = 1.0;
+ decoder->gstVolume = 0.5;
decoder->gstMuted = FALSE;
decoder->state = GST_STATE_VOID_PENDING; /* No real state yet */
pthread_mutex_init(&decoder->gst_mutex, NULL);
diff --git a/channels/tsmf/client/tsmf_ifman.c b/channels/tsmf/client/tsmf_ifman.c
index 59059dbba..03229adb5 100644
--- a/channels/tsmf/client/tsmf_ifman.c
+++ b/channels/tsmf/client/tsmf_ifman.c
@@ -127,8 +127,6 @@ int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman)
return 0;
}
-static TSMF_PRESENTATION* pexisted = 0;
-
int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
{
int status = 0;
@@ -136,15 +134,16 @@ int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
DEBUG_DVC("");
- if (pexisted)
+ presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
+ if (presentation)
{
+ DEBUG_DVC("Presentation already exists");
ifman->output_pending = FALSE;
return 0;
}
presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback);
- pexisted = presentation;
if (presentation == NULL)
status = 1;
@@ -283,8 +282,8 @@ int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
if (presentation)
tsmf_presentation_free(presentation);
-
- pexisted = 0;
+ else
+ DEBUG_WARN("unknown presentation id");
Stream_EnsureRemainingCapacity(ifman->output, 4);
Stream_Write_UINT32(ifman->output, 0); /* Result */
diff --git a/channels/tsmf/client/tsmf_media.c b/channels/tsmf/client/tsmf_media.c
index d1449237e..f31175150 100644
--- a/channels/tsmf/client/tsmf_media.c
+++ b/channels/tsmf/client/tsmf_media.c
@@ -84,6 +84,9 @@ struct _TSMF_PRESENTATION
UINT64 audio_start_time;
UINT64 audio_end_time;
+ UINT32 volume;
+ UINT32 muted;
+
HANDLE mutex;
HANDLE thread;
@@ -282,6 +285,9 @@ TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCal
memcpy(presentation->presentation_id, guid, GUID_SIZE);
presentation->channel_callback = pChannelCallback;
+ presentation->volume = 5000; /* 50% */
+ presentation->muted = 0;
+
presentation->mutex = CreateMutex(NULL, FALSE, NULL);
presentation->stream_list = list_new();
@@ -786,6 +792,9 @@ void tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 ne
LIST_ITEM* item;
TSMF_STREAM* stream;
+ presentation->volume = newVolume;
+ presentation->muted = muted;
+
for (item = presentation->stream_list->head; item; item = item->next)
{
stream = (TSMF_STREAM*) item->data;
@@ -964,7 +973,10 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id)
stream->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, stream, CREATE_SUSPENDED, NULL);
stream->sample_list = Queue_New(TRUE, -1, -1);
+ stream->sample_list->object.fnObjectFree = free;
+
stream->sample_ack_list = Queue_New(TRUE, -1, -1);
+ stream->sample_ack_list->object.fnObjectFree = free;
WaitForSingleObject(presentation->mutex, INFINITE);
list_enqueue(presentation->stream_list, stream);
@@ -1026,6 +1038,7 @@ void tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, wStream* s)
stream->width = mediatype.Width;
stream->height = mediatype.Height;
stream->decoder = tsmf_load_decoder(name, &mediatype);
+ tsmf_stream_change_volume(stream, stream->presentation->volume, stream->presentation->muted);
}
void tsmf_stream_end(TSMF_STREAM* stream)
diff --git a/client/Android/FreeRDPCore/jni/android_freerdp.c b/client/Android/FreeRDPCore/jni/android_freerdp.c
index 632ca82c2..f0046dcc5 100644
--- a/client/Android/FreeRDPCore/jni/android_freerdp.c
+++ b/client/Android/FreeRDPCore/jni/android_freerdp.c
@@ -686,7 +686,8 @@ JNIEXPORT void JNICALL jni_freerdp_set_gateway_info(JNIEnv *env, jclass cls, jin
settings->GatewayUsername = strdup(gatewayusername);
settings->GatewayPassword = strdup(gatewaypassword);
settings->GatewayDomain = strdup(gatewaydomain);
- settings->GatewayUsageMethod = TRUE;
+ settings->GatewayUsageMethod = TSC_PROXY_MODE_DIRECT;
+ settings->GatewayEnabled = TRUE;
settings->GatewayUseSameCredentials = FALSE;
(*env)->ReleaseStringUTFChars(env, jgatewayhostname, gatewayhostname);
diff --git a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionActivity.java
index 055b48b73..defaf9247 100644
--- a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionActivity.java
+++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/SessionActivity.java
@@ -248,6 +248,9 @@ public class SessionActivity extends Activity
{
Log.v(TAG, "OnConnectionFailure");
+ // remove pending move events
+ uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT);
+
if(progressDialog != null)
{
progressDialog.dismiss();
@@ -264,7 +267,10 @@ public class SessionActivity extends Activity
private void OnDisconnected(Context context)
{
Log.v(TAG, "OnDisconnected");
-
+
+ // remove pending move events
+ uiHandler.removeMessages(UIHandler.SEND_MOVE_EVENT);
+
if(progressDialog != null)
{
progressDialog.dismiss();
@@ -434,6 +440,7 @@ public class SessionActivity extends Activity
keyboardMapper = new KeyboardMapper();
keyboardMapper.init(this);
+ keyboardMapper.reset(this);
modifiersKeyboard = new Keyboard(getApplicationContext(), R.xml.modifiers_keyboard);
specialkeysKeyboard = new Keyboard(getApplicationContext(), R.xml.specialkeys_keyboard);
diff --git a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/ClipboardManagerProxy.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/ClipboardManagerProxy.java
index 83f6ca562..06b800a80 100644
--- a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/ClipboardManagerProxy.java
+++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/ClipboardManagerProxy.java
@@ -65,7 +65,9 @@ public abstract class ClipboardManagerProxy {
String data = null;
if (clip != null && clip.getItemCount() > 0) {
- data = clip.getItemAt(0).getText().toString();
+ CharSequence cs = clip.getItemAt(0).getText();
+ if (cs != null)
+ data = cs.toString();
}
if (mListener != null) {
mListener.onClipboardChanged(data);
diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt
index 78dfca32b..8b7ae739f 100755
--- a/client/Mac/CMakeLists.txt
+++ b/client/Mac/CMakeLists.txt
@@ -106,15 +106,15 @@ if (${BUILD_SHARED_LIBS})
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"$"
- "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/Contents/$"
+ "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Contents/$"
COMMENT "Copying ${LIB} to output directory"
COMMAND install_name_tool -change "$"
- "@executable_path/../Frameworks/${MODULE_NAME}.framework/Contents/$"
- "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/${MODULE_NAME}"
+ "@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$"
+ "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/${MODULE_NAME}"
COMMENT Setting install name for ${LIB}
COMMAND "${CMAKE_COMMAND}" -E echo install_name_tool -change "$"
- "@executable_path/../Frameworks/${MODULE_NAME}.framework/Contents/$"
- "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/${MODULE_NAME}")
+ "@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$"
+ "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/${MODULE_NAME}")
endforeach()
# Call install_name_tool to reassign the library install names in dependent libraries
@@ -123,8 +123,8 @@ if (${BUILD_SHARED_LIBS})
# message("adding post-build dependency: ${LIB}")
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
COMMAND install_name_tool -change "$"
- "@executable_path/../Frameworks/${MODULE_NAME}.framework/Contents/$"
- "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/Contents/$"
+ "@executable_path/../Frameworks/${MODULE_OUTPUT_NAME}.framework/Contents/$"
+ "${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Contents/$"
COMMENT Setting install name for ${LIB} in module ${DEST})
endforeach()
endforeach()
@@ -145,7 +145,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles")
# Make sure the 'Resources' Directory is correctly created before we build
add_custom_command(TARGET ${MODULE_NAME} PRE_BUILD
- COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.app/Contents/Resources)
+ COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Versions/${MACOSX_BUNDLE_SHORT_VERSION_STRING}/Resources)
# Compile the .xib files using the 'ibtool' program with the destination being the app package
foreach(xib ${${MODULE_NAME}_XIBS})
@@ -153,7 +153,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles")
add_custom_command (TARGET ${MODULE_NAME} POST_BUILD
COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text
- --compile ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.app/Contents/Resources/${XIB_WE}.nib ${xib}
+ --compile ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Versions/${MACOSX_BUNDLE_SHORT_VERSION_STRING}/Resources/${XIB_WE}.nib ${xib}
COMMENT "Compiling ${xib}")
endforeach()
endif()
@@ -162,13 +162,13 @@ endif()
foreach(HEADER ${${MODULE_NAME}_HEADERS})
# message("adding post-build dependency: ${LIB}")
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
- COMMAND ditto ${HEADER} ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/Headers/
+ COMMAND ditto ${HEADER} ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Headers/
COMMENT Copying public header files to ${MODULE_NAME})
endforeach()
# Copy the FreeRDP header files into the framework
add_custom_command(TARGET ${MODULE_NAME} POST_BUILD
- COMMAND ditto ${CMAKE_SOURCE_DIR}/include/freerdp ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_NAME}.framework/Headers/freerdp
+ COMMAND ditto ${CMAKE_SOURCE_DIR}/include/freerdp ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Headers/freerdp
COMMENT Copying FreeRDP header files to ${MODULE_NAME})
add_subdirectory(cli)
diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h
index 2cc67c2d4..653c2d391 100755
--- a/client/Mac/MRDPView.h
+++ b/client/Mac/MRDPView.h
@@ -78,6 +78,8 @@
int kdlmeta;
int kdrmeta;
int kdcapslock;
+
+ BOOL initialized;
@public
NSPasteboard* pasteboard_rd; /* for reading from clipboard */
@@ -107,3 +109,8 @@
#define PTR_FLAGS_BUTTON2 0x2000
#define PTR_FLAGS_BUTTON3 0x4000
#define WheelRotationMask 0x01FF
+
+BOOL mac_pre_connect(freerdp* instance);
+BOOL mac_post_connect(freerdp* instance);
+BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain);
+int mac_receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size);
diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m
index fe516b543..c92731914 100644
--- a/client/Mac/MRDPView.m
+++ b/client/Mac/MRDPView.m
@@ -75,9 +75,6 @@ void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer);
void mf_Pointer_SetNull(rdpContext* context);
void mf_Pointer_SetDefault(rdpContext* context);
// int rdp_connect(void);
-BOOL mac_pre_connect(freerdp* instance);
-BOOL mac_post_connect(freerdp* instance);
-BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain);
void mac_set_bounds(rdpContext* context, rdpBounds* bounds);
void mac_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap);
void mac_begin_paint(rdpContext* context);
@@ -129,28 +126,19 @@ struct rgba_data
rdpSettings* settings;
EmbedWindowEventArgs e;
+ [self initializeView];
+
context = rdp_context;
mfc = (mfContext*) rdp_context;
instance = context->instance;
settings = context->settings;
- mfc->view = self;
EventArgsInit(&e, "mfreerdp");
e.embed = TRUE;
e.handle = (void*) self;
PubSub_OnEmbedWindow(context->pubSub, context, &e);
- context->instance->PreConnect = mac_pre_connect;
- context->instance->PostConnect = mac_post_connect;
- context->instance->ReceiveChannelData = mac_receive_channel_data;
- context->instance->Authenticate = mac_authenticate;
-
- // TODO
- // instance->Authenticate = mf_authenticate;
- // instance->VerifyCertificate = mf_verify_certificate;
- // instance->LogonErrorInfo = mf_logon_error_info;
-
- status = freerdp_connect(context->instance);
+ status = freerdp_connect(context->instance);
if (!status)
{
@@ -185,7 +173,7 @@ struct rgba_data
- (id)initWithFrame:(NSRect)frame
{
- self = [super initWithFrame:frame];
+ self = [super initWithFrame:frame];
if (self)
{
@@ -201,24 +189,34 @@ struct rgba_data
//TODO - Expose this code as a public method, because awakeFromNib
// won't be called if the view is created dynamically
-- (void) awakeFromNib
+- (void) viewDidLoad
{
- // store our window dimensions
- width = [self frame].size.width;
- height = [self frame].size.height;
- titleBarHeight = 22;
-
- [[self window] becomeFirstResponder];
- [[self window] setAcceptsMouseMovedEvents:YES];
-
- cursors = [[NSMutableArray alloc] initWithCapacity:10];
+ [self initializeView];
+}
- // setup a mouse tracking area
- NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil];
-
- [self addTrackingArea:trackingArea];
-
- mouseInClientArea = YES;
+- (void) initializeView
+{
+ if (!initialized)
+ {
+ // store our window dimensions
+ width = [self frame].size.width;
+ height = [self frame].size.height;
+ titleBarHeight = 22;
+
+ [[self window] becomeFirstResponder];
+ [[self window] setAcceptsMouseMovedEvents:YES];
+
+ cursors = [[NSMutableArray alloc] initWithCapacity:10];
+
+ // setup a mouse tracking area
+ NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil];
+
+ [self addTrackingArea:trackingArea];
+
+ mouseInClientArea = YES;
+
+ initialized = YES;
+ }
}
/** *********************************************************************
@@ -619,11 +617,6 @@ struct rgba_data
if (run_loop_src_channels != 0)
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_src_channels, kCFRunLoopDefaultMode);
-
- freerdp_client_stop(self->context);
-
- freerdp_client_context_free(self->context);
-
}
/** *********************************************************************
@@ -782,8 +775,17 @@ struct rgba_data
outerRect.size.height = h + heightDiff;
[[self window] setMaxSize:outerRect.size];
[[self window] setMinSize:outerRect.size];
- [[self window] setFrame:outerRect display:YES];
-
+
+ @try
+ {
+ [[self window] setFrame:outerRect display:YES];
+ }
+ @catch (NSException * e) {
+ NSLog(@"Exception: %@", e);
+ }
+ @finally {
+ }
+
// set client area to specified dimensions
innerRect.size.width = w;
innerRect.size.height = h;
@@ -868,8 +870,7 @@ BOOL mac_pre_connect(freerdp* instance)
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
- [view setViewSize :instance->settings->DesktopWidth :instance->settings->DesktopHeight];
-
+ [view setViewSize :instance->settings->DesktopWidth :instance->settings->DesktopHeight];
freerdp_channels_pre_connect(instance->context->channels, instance);
return TRUE;
@@ -888,13 +889,7 @@ BOOL mac_pre_connect(freerdp* instance)
BOOL mac_post_connect(freerdp* instance)
{
- int index;
- int fds[32];
UINT32 flags;
- int rd_count = 0;
- int wr_count = 0;
- void* rd_fds[32];
- void* wr_fds[32];
rdpPointer rdp_pointer;
mfContext *mfc = (mfContext*) instance->context;
@@ -908,7 +903,7 @@ BOOL mac_post_connect(freerdp* instance)
rdp_pointer.SetNull = mf_Pointer_SetNull;
rdp_pointer.SetDefault = mf_Pointer_SetDefault;
- flags = CLRBUF_32BPP;
+ flags = CLRBUF_32BPP | CLRCONV_ALPHA;
gdi_init(instance, flags, NULL);
rdpGdi* gdi = instance->context->gdi;
@@ -927,9 +922,6 @@ BOOL mac_post_connect(freerdp* instance)
view->pasteboard_rd = [NSPasteboard generalPasteboard];
view->pasteboard_changecount = (int) [view->pasteboard_rd changeCount];
view->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:mfc->view selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES];
-
- /* we want to be notified when window resizes */
- [[NSNotificationCenter defaultCenter] addObserver:mfc->view selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:nil];
return TRUE;
}
@@ -983,7 +975,7 @@ void mf_Pointer_New(rdpContext* context, rdpPointer* pointer)
MRDPCursor* mrdpCursor = [[MRDPCursor alloc] init];
mfContext* mfc = (mfContext*) context;
MRDPView* view = (MRDPView*) mfc->view;
-
+
rect.size.width = pointer->width;
rect.size.height = pointer->height;
rect.origin.x = pointer->xPos;
@@ -994,10 +986,7 @@ void mf_Pointer_New(rdpContext* context, rdpPointer* pointer)
freerdp_alpha_cursor_convert(cursor_data, pointer->xorMaskData, pointer->andMaskData,
pointer->width, pointer->height, pointer->xorBpp, context->gdi->clrconv);
-
- // TODO if xorBpp is > 24 need to call freerdp_image_swap_color_order
- // see file df_graphics.c
-
+
/* store cursor bitmap image in representation - required by NSImage */
bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &cursor_data
pixelsWide:rect.size.width
@@ -1065,8 +1054,6 @@ void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer)
MRDPView* view = (MRDPView*) mfc->view;
NSMutableArray* ma = view->cursors;
-
- return; /* disable pointer until it is fixed */
if (!view->mouseInClientArea)
return;
@@ -1152,10 +1139,10 @@ void mac_end_paint(rdpContext* context)
for (i = 0; i < gdi->primary->hdc->hwnd->ninvalid; i++)
{
- drawRect.origin.x = gdi->primary->hdc->hwnd->cinvalid[i].x;
- drawRect.origin.y = gdi->primary->hdc->hwnd->cinvalid[i].y;
- drawRect.size.width = gdi->primary->hdc->hwnd->cinvalid[i].w;
- drawRect.size.height = gdi->primary->hdc->hwnd->cinvalid[i].h;
+ drawRect.origin.x = gdi->primary->hdc->hwnd->cinvalid[i].x - 1;
+ drawRect.origin.y = gdi->primary->hdc->hwnd->cinvalid[i].y - 1;
+ drawRect.size.width = gdi->primary->hdc->hwnd->cinvalid[i].w + 1;
+ drawRect.size.height = gdi->primary->hdc->hwnd->cinvalid[i].h + 1;
windows_to_apple_cords(mfc->view, &drawRect);
[view setNeedsDisplayInRect:drawRect];
}
@@ -1235,6 +1222,7 @@ static void channel_activity_cb(CFFileDescriptorRef fdref, CFOptionFlags callBac
freerdp_channels_process_pending_messages(instance);
event = freerdp_channels_pop_event(instance->context->channels);
+
if (event)
{
switch (GetMessageClass(event->id))
diff --git a/client/Mac/cli/AppDelegate.h b/client/Mac/cli/AppDelegate.h
index fe2671351..2ce5ca858 100644
--- a/client/Mac/cli/AppDelegate.h
+++ b/client/Mac/cli/AppDelegate.h
@@ -7,8 +7,8 @@
//
#import
-#import
-#import
+#import
+#import
@interface AppDelegate : NSObject
{
@@ -20,6 +20,5 @@
@property (assign) IBOutlet NSWindow *window;
@property (assign) rdpContext *context;
-@property (assign) IBOutlet MRDPView *mrdpView;
@end
diff --git a/client/Mac/cli/AppDelegate.m b/client/Mac/cli/AppDelegate.m
index 1eb3d13c1..6c53f4805 100644
--- a/client/Mac/cli/AppDelegate.m
+++ b/client/Mac/cli/AppDelegate.m
@@ -7,8 +7,12 @@
//
#import "AppDelegate.h"
-#import "MacFreeRDP-library/mfreerdp.h"
-#import "MacFreeRDP-library/mf_client.h"
+#import "MacFreeRDP/mfreerdp.h"
+#import "MacFreeRDP/mf_client.h"
+
+static AppDelegate* _singleDelegate = nil;
+void AppDelegate_EmbedWindowEventHandler(rdpContext* context, EmbedWindowEventArgs* e);
+
@implementation AppDelegate
@@ -19,7 +23,6 @@
@synthesize window = window;
-@synthesize mrdpView = mrdpView;
@synthesize context = context;
@@ -28,6 +31,7 @@
int status;
mfContext* mfc;
+ _singleDelegate = self;
[self CreateContext];
status = [self ParseCommandLineArguments];
@@ -41,6 +45,7 @@
}
else
{
+ PubSub_Subscribe(context->pubSub, "EmbedWindow", (pEventHandler) AppDelegate_EmbedWindowEventHandler);
freerdp_client_start(context);
}
}
@@ -48,6 +53,7 @@
- (void) applicationWillTerminate:(NSNotification*)notification
{
[mrdpView releaseResources];
+ _singleDelegate = nil;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
@@ -103,4 +109,19 @@
context = nil;
}
+
@end
+
+void AppDelegate_EmbedWindowEventHandler(rdpContext* context, EmbedWindowEventArgs* e)
+{
+ if (_singleDelegate)
+ {
+ mfContext* mfc = (mfContext*) context;
+ _singleDelegate->mrdpView = mfc->view;
+
+ if (_singleDelegate->window)
+ {
+ [[_singleDelegate->window contentView] addSubview:mfc->view];
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/Mac/cli/MainMenu.xib b/client/Mac/cli/MainMenu.xib
index 90e992462..65e72b118 100755
--- a/client/Mac/cli/MainMenu.xib
+++ b/client/Mac/cli/MainMenu.xib
@@ -2,18 +2,16 @@
1070
- 12D78
+ 12E55
3084
- 1187.37
+ 1187.39
626.00
- IBNSLayoutConstraint
NSCustomObject
- NSCustomView
NSMenu
NSMenuItem
NSView
@@ -257,24 +255,12 @@
- {{0, 0}, {1440, 878}}
+ {{0, 0}, {1920, 1178}}
{1024, 790}
{1024, 790}
128
@@ -369,14 +355,6 @@
493
-
-
- mrdpView
-
-
-
- 569
-
window
@@ -551,73 +529,7 @@
372
-
-
-
-
- 6
- 0
-
- 6
- 1
-
- 0.0
-
- 1000
-
- 8
- 29
- 3
-
-
-
- 5
- 0
-
- 5
- 1
-
- 0.0
-
- 1000
-
- 8
- 29
- 3
-
-
-
- 4
- 0
-
- 4
- 1
-
- 0.0
-
- 1000
-
- 8
- 29
- 3
-
-
-
- 3
- 0
-
- 3
- 1
-
- 0.0
-
- 1000
-
- 8
- 29
- 3
-
-
+
@@ -657,31 +569,6 @@
-
- 551
-
-
-
-
- 561
-
-
-
-
- 562
-
-
-
-
- 563
-
-
-
-
- 564
-
-
-
@@ -706,12 +593,6 @@
com.apple.InterfaceBuilder.CocoaPlugin
{{380, 496}, {480, 360}}
-
-
-
-
-
-
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
@@ -720,13 +601,7 @@
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
-
- com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
- com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
@@ -738,48 +613,7 @@
570
-
-
-
- AppDelegate
- NSObject
-
- MRDPView
- NSWindow
-
-
-
- mrdpView
- MRDPView
-
-
- window
- NSWindow
-
-
-
- IBProjectSource
- ./Classes/AppDelegate.h
-
-
-
- MRDPView
- NSView
-
- IBProjectSource
- ./Classes/MRDPView.h
-
-
-
- NSLayoutConstraint
- NSObject
-
- IBProjectSource
- ./Classes/NSLayoutConstraint.h
-
-
-
-
+
0
IBCocoaFramework
diff --git a/client/Mac/mf_client.m b/client/Mac/mf_client.m
index 20aa3ce01..900c488ed 100755
--- a/client/Mac/mf_client.m
+++ b/client/Mac/mf_client.m
@@ -25,6 +25,7 @@
#include
#include
#include
+#import "MRDPView.h"
/**
* Client Interface
@@ -46,6 +47,13 @@ int mfreerdp_client_start(rdpContext* context)
MRDPView* view;
mfContext* mfc = (mfContext*) context;
+ if (mfc->view == NULL)
+ {
+ // view not specified beforehand. Create view dynamically
+ mfc->view = [[MRDPView alloc] initWithFrame : NSMakeRect(0, 0, context->settings->DesktopWidth, context->settings->DesktopHeight)];
+ mfc->view_ownership = TRUE;
+ }
+
view = (MRDPView*) mfc->view;
[view rdpStart:context];
@@ -60,20 +68,34 @@ int mfreerdp_client_stop(rdpContext* context)
{
wMessageQueue* queue;
queue = freerdp_get_message_queue(context->instance, FREERDP_UPDATE_MESSAGE_QUEUE);
- MessageQueue_PostQuit(queue, 0);
+ if (queue)
+ {
+ MessageQueue_PostQuit(queue, 0);
+ }
}
if (context->settings->AsyncInput)
{
wMessageQueue* queue;
queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE);
- MessageQueue_PostQuit(queue, 0);
- }
+ if (queue)
+ {
+ MessageQueue_PostQuit(queue, 0);
+ }
+ }
else
{
mfc->disconnect = TRUE;
}
+ if (mfc->view_ownership)
+ {
+ MRDPView* view = (MRDPView*) mfc->view;
+ [view releaseResources];
+ [view release];
+ mfc->view = nil;
+ }
+
return 0;
}
@@ -84,7 +106,12 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context)
mfc = (mfContext*) instance->context;
- context->channels = freerdp_channels_new();
+ context->instance->PreConnect = mac_pre_connect;
+ context->instance->PostConnect = mac_post_connect;
+ context->instance->ReceiveChannelData = mac_receive_channel_data;
+ context->instance->Authenticate = mac_authenticate;
+
+ context->channels = freerdp_channels_new();
settings = instance->settings;
diff --git a/client/Mac/mfreerdp.h b/client/Mac/mfreerdp.h
index 02b0272e2..ff3bd6176 100644
--- a/client/Mac/mfreerdp.h
+++ b/client/Mac/mfreerdp.h
@@ -28,6 +28,7 @@ struct mf_context
DEFINE_RDP_CLIENT_COMMON();
void* view;
+ BOOL view_ownership; // TRUE indicates that the window was created and should be freed by the API.
int width;
int height;
diff --git a/client/X11/xf_channels.c b/client/X11/xf_channels.c
index 91dda0b8e..24325046e 100644
--- a/client/X11/xf_channels.c
+++ b/client/X11/xf_channels.c
@@ -26,19 +26,17 @@
#include "xf_client.h"
#include "xfreerdp.h"
-int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface)
+void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e)
{
- xfContext* xfc = (xfContext*) instance->context;
+ xfContext* xfc = (xfContext*) context;
- if (strcmp(name, RDPEI_DVC_CHANNEL_NAME) == 0)
+ if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
- xfc->rdpei = (RdpeiClientContext*) pInterface;
+ xfc->rdpei = (RdpeiClientContext*) e->pInterface;
}
-
- return 0;
}
-int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface)
+void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e)
{
- return 0;
+
}
diff --git a/client/X11/xf_channels.h b/client/X11/xf_channels.h
index 1aeaf1a66..bb52d5e52 100644
--- a/client/X11/xf_channels.h
+++ b/client/X11/xf_channels.h
@@ -27,4 +27,7 @@
int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface);
int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface);
+void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e);
+void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e);
+
#endif
diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c
index 760daab97..7f313fadd 100644
--- a/client/X11/xf_client.c
+++ b/client/X11/xf_client.c
@@ -750,8 +750,11 @@ BOOL xf_pre_connect(freerdp* instance)
settings = instance->settings;
channels = instance->context->channels;
- instance->OnChannelConnected = xf_on_channel_connected;
- instance->OnChannelDisconnected = xf_on_channel_disconnected;
+ PubSub_SubscribeChannelConnected(instance->context->pubSub,
+ (pChannelConnectedEventHandler) xf_OnChannelConnectedEventHandler);
+
+ PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
+ (pChannelDisconnectedEventHandler) xf_OnChannelDisconnectedEventHandler);
freerdp_client_load_addins(channels, instance->settings);
diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c
index 17b9eb73b..0c4c14759 100644
--- a/client/X11/xf_event.c
+++ b/client/X11/xf_event.c
@@ -178,6 +178,9 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window win
static BOOL xf_event_MotionNotify(xfContext* xfc, XEvent* event, BOOL app)
{
+ if (xfc->use_xinput)
+ return TRUE;
+
return xf_generic_MotionNotify(xfc, event->xmotion.x, event->xmotion.y,
event->xmotion.state, event->xmotion.window, app);
}
@@ -283,6 +286,9 @@ BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window win
static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app)
{
+ if (xfc->use_xinput)
+ return TRUE;
+
return xf_generic_ButtonPress(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app);
}
@@ -295,6 +301,7 @@ BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window w
rdpInput* input;
Window childWindow;
+
flags = 0;
wheel = FALSE;
extended = FALSE;
@@ -366,6 +373,9 @@ BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window w
static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app)
{
+ if (xfc->use_xinput)
+ return TRUE;
+
return xf_generic_ButtonRelease(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app);
}
diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c
index 96fbf974d..8b185ce7e 100644
--- a/client/X11/xf_graphics.c
+++ b/client/X11/xf_graphics.c
@@ -131,7 +131,7 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
RFX_MESSAGE* msg;
xfContext* xfc = (xfContext*) context;
- size = width * height * (bpp + 7) / 8;
+ size = width * height * ((bpp + 7) / 8);
if (bitmap->data == NULL)
bitmap->data = (BYTE*) malloc(size);
diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c
index 935a9533b..d57c342e9 100644
--- a/client/X11/xf_input.c
+++ b/client/X11/xf_input.c
@@ -183,8 +183,11 @@ int xf_input_init(xfContext* xfc, Window window)
if (xfc->use_xinput)
{
- if (!touch && (class->type == XIButtonClass))
+ if (!touch && (class->type == XIButtonClass) && strcmp(dev->name, "Virtual core pointer"))
{
+ printf("%s button device (id: %d, mode: %d)\n",
+ dev->name,
+ dev->deviceid, t->mode);
XISetMask(masks[nmasks], XI_ButtonPress);
XISetMask(masks[nmasks], XI_ButtonRelease);
XISetMask(masks[nmasks], XI_Motion);
@@ -597,24 +600,23 @@ int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtype)
int xf_input_event(xfContext* xfc, XIDeviceEvent* event, int evtype)
{
- return TRUE;
switch (evtype)
{
case XI_ButtonPress:
- //printf("ButtonPress\n");
+
xf_generic_ButtonPress(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app);
break;
case XI_ButtonRelease:
- //printf("ButtonRelease\n");
+
xf_generic_ButtonRelease(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app);
break;
case XI_Motion:
- //printf("Motion\n");
+
xf_generic_MotionNotify(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app);
break;
diff --git a/client/common/client.c b/client/common/client.c
index acc47d064..824b46859 100644
--- a/client/common/client.c
+++ b/client/common/client.c
@@ -56,8 +56,8 @@ rdpContext* freerdp_client_context_new(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
freerdp_context_new(instance);
context = instance->context;
- context->instance = instance;
- context->settings = instance->settings;
+ context->instance = instance;
+ context->settings = instance->settings;
return context;
}
@@ -112,16 +112,13 @@ int freerdp_client_parse_command_line(rdpContext* context, int argc, char** argv
if (settings->ConnectionFile)
{
- rdpFile* file = freerdp_client_rdp_file_new();
- freerdp_client_parse_rdp_file(file, settings->ConnectionFile);
- freerdp_client_populate_settings_from_rdp_file(file, settings);
- freerdp_client_rdp_file_free(file);
+ return freerdp_client_parse_connection_file(context, settings->ConnectionFile);
}
return status;
}
-int freerdp_client_parse_connection_file(rdpContext* context, char* filename)
+int freerdp_client_parse_connection_file(rdpContext* context, const char* filename)
{
rdpFile* file;
@@ -136,11 +133,35 @@ int freerdp_client_parse_connection_file(rdpContext* context, char* filename)
int freerdp_client_parse_connection_file_buffer(rdpContext* context, BYTE* buffer, size_t size)
{
rdpFile* file;
+ int status = -1;
file = freerdp_client_rdp_file_new();
- freerdp_client_parse_rdp_file_buffer(file, buffer, size);
- freerdp_client_populate_settings_from_rdp_file(file, context->settings);
+ if (freerdp_client_parse_rdp_file_buffer(file, buffer, size)
+ && freerdp_client_populate_settings_from_rdp_file(file, context->settings))
+ {
+ status = 0;
+ }
+
freerdp_client_rdp_file_free(file);
- return 0;
+ return status;
+}
+
+int freerdp_client_write_connection_file(rdpContext* context, const char* filename, BOOL unicode)
+{
+ rdpFile* file;
+ int status = -1;
+
+ file = freerdp_client_rdp_file_new();
+ if (freerdp_client_populate_rdp_file_from_settings(file, context->settings))
+ {
+ if (freerdp_client_write_rdp_file(file, filename, unicode))
+ {
+ status = 0;
+ }
+ }
+
+ freerdp_client_rdp_file_free(file);
+
+ return status;
}
diff --git a/client/common/cmdline.c b/client/common/cmdline.c
index cb2af914d..891716b1a 100644
--- a/client/common/cmdline.c
+++ b/client/common/cmdline.c
@@ -92,6 +92,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "multitouch", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect multitouch input" },
{ "gestures", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Consume multitouch input locally" },
{ "echo", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "echo", "Echo channel" },
+ { "disp", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Display control" },
{ "fonts", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Smooth fonts (ClearType)" },
{ "aero", COMMAND_LINE_VALUE_BOOL, NULL, NULL, BoolValueFalse, -1, NULL, "Desktop composition" },
{ "window-drag", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Full window drag" },
@@ -135,6 +136,8 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "wm-class", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "set the WM_CLASS hint for the window instance" },
{ "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, NULL, "print version" },
{ "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "print help" },
+ { "play-rfx", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Replay rfx pcap file" },
+ { "auth-only", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Authenticate only." },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
@@ -617,6 +620,16 @@ int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_ARGUMENT
freerdp_client_add_dynamic_channel(settings, count, p);
}
+ CommandLineSwitchCase(arg, "disp")
+ {
+ char* p[1];
+ int count;
+
+ count = 1;
+ p[0] = "disp";
+
+ freerdp_client_add_dynamic_channel(settings, count, p);
+ }
CommandLineSwitchCase(arg, "sound")
{
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
@@ -875,13 +888,10 @@ int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, int*
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
- if (detect_status == 0)
- {
- if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
- detect_status = -1;
- }
+ if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
+ detect_status = -1;
- return 0;
+ return detect_status;
}
int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv, int* count)
@@ -911,13 +921,10 @@ int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv, int* c
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
- if (detect_status == 0)
- {
- if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
- detect_status = -1;
- }
+ if ((status <= COMMAND_LINE_ERROR) && (status >= COMMAND_LINE_ERROR_LAST))
+ detect_status = -1;
- return 0;
+ return detect_status;
}
BOOL freerdp_client_detect_command_line(int argc, char** argv, DWORD* flags)
@@ -1044,6 +1051,7 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
freerdp_client_command_line_pre_filter, freerdp_client_command_line_post_filter);
}
+
arg = CommandLineFindArgumentA(args, "v");
arg = args;
@@ -1253,8 +1261,9 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
settings->GatewayHostname = _strdup(settings->ServerHostname);
}
- settings->GatewayUsageMethod = TRUE;
+ settings->GatewayUsageMethod = TSC_PROXY_MODE_DIRECT;
settings->GatewayUseSameCredentials = TRUE;
+ settings->GatewayEnabled = TRUE;
}
CommandLineSwitchCase(arg, "gu")
{
@@ -1438,6 +1447,7 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
CommandLineSwitchCase(arg, "nsc")
{
settings->NSCodec = TRUE;
+ settings->ColorDepth = 32;
}
CommandLineSwitchCase(arg, "jpeg")
{
@@ -1609,6 +1619,15 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
{
settings->WmClass = _strdup(arg->Value);
}
+ CommandLineSwitchCase(arg, "play-rfx")
+ {
+ settings->PlayRemoteFxFile = _strdup(arg->Value);
+ settings->PlayRemoteFx = TRUE;
+ }
+ CommandLineSwitchCase(arg, "auth-only")
+ {
+ settings->AuthenticationOnly = arg->Value ? TRUE : FALSE;
+ }
CommandLineSwitchDefault(arg)
{
@@ -1638,7 +1657,7 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
if (settings->DisableThemes)
settings->PerformanceFlags |= PERF_DISABLE_THEMING;
- if (settings->GatewayUsageMethod)
+ if (settings->GatewayEnabled)
{
if (settings->GatewayUseSameCredentials)
{
@@ -1667,7 +1686,7 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
FillMemory(arg->Value, strlen(arg->Value), '*');
}
- return 1;
+ return status;
}
int freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpSettings* settings, char* name, void* data)
diff --git a/client/common/file.c b/client/common/file.c
index afe40e9b1..324b4d619 100644
--- a/client/common/file.c
+++ b/client/common/file.c
@@ -439,7 +439,7 @@ BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, BYTE* buffer, size_t si
return freerdp_client_parse_rdp_file_buffer_ascii(file, buffer, size);
}
-BOOL freerdp_client_parse_rdp_file(rdpFile* file, char* name)
+BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name)
{
BYTE* buffer;
FILE* fp = NULL;
@@ -480,7 +480,8 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, char* name)
return freerdp_client_parse_rdp_file_buffer(file, buffer, file_size);
}
-#define SETTING_MODIFIED(_settings, _field) (_settings->settings_modified[FreeRDP_##_field])
+#define WRITE_ALL_SETTINGS TRUE
+#define SETTING_MODIFIED(_settings, _field) (WRITE_ALL_SETTINGS || _settings->settings_modified[FreeRDP_##_field])
#define SETTING_MODIFIED_SET(_target, _settings, _field) if SETTING_MODIFIED(_settings, _field) _target = _settings->_field
BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings* settings)
@@ -529,9 +530,9 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings*
}
-BOOL freerdp_client_write_rdp_file(rdpFile* file, char* name, BOOL unicode)
+BOOL freerdp_client_write_rdp_file(rdpFile* file, const char* name, BOOL unicode)
{
- BOOL success = FALSE;
+ int rc = 0;
char* buffer;
int len, len2;
FILE* fp = NULL;
@@ -559,22 +560,22 @@ BOOL freerdp_client_write_rdp_file(rdpFile* file, char* name, BOOL unicode)
fwrite(BOM_UTF16_LE, sizeof(BYTE), 2, fp);
fwrite(unicodestr, 2, len, fp);
- free(unicodestr);
+ free(unicodestr);
}
else
{
fwrite(buffer, 1, len, fp);
}
- fflush(fp);
- fclose(fp);
+ rc = fflush(fp);
+ rc = fclose(fp);
}
}
if (buffer != NULL)
free(buffer);
- return success;
+ return (rc == 0);
}
#define WRITE_RDP_FILE_DECLARE(_file, _buffer, _size) \
@@ -731,11 +732,19 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
if (~((size_t) file->GatewayHostname))
freerdp_set_param_string(settings, FreeRDP_GatewayHostname, file->GatewayHostname);
+
if (~file->GatewayUsageMethod)
- freerdp_set_param_bool(settings, FreeRDP_GatewayUsageMethod, file->GatewayUsageMethod);
+ {
+ freerdp_set_param_uint32(settings, FreeRDP_GatewayUsageMethod, file->GatewayUsageMethod);
+
+ if (file->GatewayUsageMethod == TSC_PROXY_MODE_DIRECT)
+ freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, TRUE);
+ else if (file->GatewayUsageMethod == TSC_PROXY_MODE_NONE_DETECT)
+ freerdp_set_param_bool(settings, FreeRDP_GatewayEnabled, FALSE);
+ }
+
if (~file->PromptCredentialOnce)
- freerdp_set_param_bool(settings, FreeRDP_GatewayUsageMethod, file->GatewayUsageMethod);
- settings->GatewayUseSameCredentials = TRUE;
+ freerdp_set_param_bool(settings, FreeRDP_GatewayUseSameCredentials, TRUE);
if (~file->RemoteApplicationMode)
freerdp_set_param_bool(settings, FreeRDP_RemoteApplicationMode, file->RemoteApplicationMode);
diff --git a/client/iOS/Models/RDPSession.m b/client/iOS/Models/RDPSession.m
index df924e29f..d61d59a57 100644
--- a/client/iOS/Models/RDPSession.m
+++ b/client/iOS/Models/RDPSession.m
@@ -175,7 +175,8 @@ NSString* TSXSessionDidFailToConnectNotification = @"TSXSessionDidFailToConnect"
settings->GatewayUsername = strdup([_params UTF8StringForKey:@"tsg_username"]);
settings->GatewayPassword = strdup([_params UTF8StringForKey:@"tsg_password"]);
settings->GatewayDomain = strdup([_params UTF8StringForKey:@"tsg_domain"]);
- settings->GatewayUsageMethod = TRUE;
+ settings->GatewayUsageMethod = TSC_PROXY_MODE_DIRECT;
+ settings->GatewayEnabled = TRUE;
settings->GatewayUseSameCredentials = FALSE;
}
diff --git a/docs/README.directfb b/docs/README.directfb
new file mode 100644
index 000000000..db72c0e85
--- /dev/null
+++ b/docs/README.directfb
@@ -0,0 +1,3 @@
+The dfreerdp FreeRDP client is currently orphaned and unmaintained so please don't expect it to build and work without problems.
+
+If you are interested to update and maintain the dfreerdp client please let us know.
diff --git a/include/freerdp/client.h b/include/freerdp/client.h
index e3f7b2eb0..af08998b5 100644
--- a/include/freerdp/client.h
+++ b/include/freerdp/client.h
@@ -97,8 +97,9 @@ FREERDP_API freerdp* freerdp_client_get_instance(rdpContext* context);
FREERDP_API HANDLE freerdp_client_get_thread(rdpContext* context);
FREERDP_API int freerdp_client_parse_command_line(rdpContext* context, int argc, char** argv);
-FREERDP_API int freerdp_client_parse_connection_file(rdpContext* context, char* filename);
+FREERDP_API int freerdp_client_parse_connection_file(rdpContext* context, const char* filename);
FREERDP_API int freerdp_client_parse_connection_file_buffer(rdpContext* context, BYTE* buffer, size_t size);
+FREERDP_API int freerdp_client_write_connection_file(rdpContext* context, const char* filename, BOOL unicode);
#ifdef __cplusplus
}
diff --git a/include/freerdp/client/disp.h b/include/freerdp/client/disp.h
new file mode 100644
index 000000000..fa747db52
--- /dev/null
+++ b/include/freerdp/client/disp.h
@@ -0,0 +1,64 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Display Update Virtual Channel Extension
+ *
+ * Copyright 2013 Marc-Andre Moreau
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FREERDP_CHANNEL_CLIENT_DISP_H
+#define FREERDP_CHANNEL_CLIENT_DISP_H
+
+#define ORIENTATION_LANDSCAPE 0
+#define ORIENTATION_PORTRAIT 90
+#define ORIENTATION_LANDSCAPE_FLIPPED 180
+#define ORIENTATION_PORTRAIT_FLIPPED 270
+
+#define DISPLAY_CONTROL_MONITOR_PRIMARY 0x00000001
+
+struct _DISPLAY_CONTROL_MONITOR_LAYOUT
+{
+ UINT32 Flags;
+ INT32 Left;
+ INT32 Top;
+ UINT32 Width;
+ UINT32 Height;
+ UINT32 PhysicalWidth;
+ UINT32 PhysicalHeight;
+ UINT32 Orientation;
+ UINT32 DesktopScaleFactor;
+ UINT32 DeviceScaleFactor;
+};
+typedef struct _DISPLAY_CONTROL_MONITOR_LAYOUT DISPLAY_CONTROL_MONITOR_LAYOUT;
+
+/**
+ * Client Interface
+ */
+
+#define DISP_DVC_CHANNEL_NAME "Microsoft::Windows::RDS::DisplayControl"
+
+typedef struct _disp_client_context DispClientContext;
+
+typedef int (*pcDispSendMonitorLayout)(DispClientContext* context, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors);
+
+struct _disp_client_context
+{
+ void* handle;
+ void* custom;
+
+ pcDispSendMonitorLayout SendMonitorLayout;
+};
+
+#endif /* FREERDP_CHANNEL_CLIENT_DISP_H */
+
diff --git a/include/freerdp/client/file.h b/include/freerdp/client/file.h
index e83aa5ced..8fffdfbe8 100644
--- a/include/freerdp/client/file.h
+++ b/include/freerdp/client/file.h
@@ -137,12 +137,12 @@ typedef struct rdp_file rdpFile;
extern "C" {
#endif
-FREERDP_API BOOL freerdp_client_parse_rdp_file(rdpFile* file, char* name);
+FREERDP_API BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name);
FREERDP_API BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, BYTE* buffer, size_t size);
FREERDP_API BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* settings);
FREERDP_API BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings* settings);
-FREERDP_API BOOL freerdp_client_write_rdp_file(rdpFile* file, char* name, BOOL unicode);
+FREERDP_API BOOL freerdp_client_write_rdp_file(rdpFile* file, const char* name, BOOL unicode);
FREERDP_API size_t freerdp_client_write_rdp_file_buffer(rdpFile* file, char* buffer, size_t size);
FREERDP_API rdpFile* freerdp_client_rdp_file_new(void);
diff --git a/include/freerdp/codec/bitmap.h b/include/freerdp/codec/bitmap.h
index a0a2e4c82..c652a921b 100644
--- a/include/freerdp/codec/bitmap.h
+++ b/include/freerdp/codec/bitmap.h
@@ -23,6 +23,12 @@
#include
#include
+#include
+#include
+
FREERDP_API BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp);
+FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height,
+ wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e);
+
#endif /* FREERDP_CODEC_BITMAP_H */
diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h
index d3ba0536a..97f5763d9 100644
--- a/include/freerdp/codec/rfx.h
+++ b/include/freerdp/codec/rfx.h
@@ -106,6 +106,8 @@ struct _RFX_CONTEXT
void (*quantization_encode)(INT16* buffer, const UINT32* quantization_values);
void (*dwt_2d_decode)(INT16* buffer, INT16* dwt_buffer);
void (*dwt_2d_encode)(INT16* buffer, INT16* dwt_buffer);
+ int (*rlgr_decode)(RLGR_MODE mode, const BYTE* data, int data_size, INT16* buffer, int buffer_size);
+ int (*rlgr_encode)(RLGR_MODE mode, const INT16* data, int data_size, BYTE* buffer, int buffer_size);
/* private definitions */
RFX_CONTEXT_PRIV* priv;
diff --git a/include/freerdp/crypto/tls.h b/include/freerdp/crypto/tls.h
index c396679b3..7e9aca995 100644
--- a/include/freerdp/crypto/tls.h
+++ b/include/freerdp/crypto/tls.h
@@ -61,6 +61,7 @@ FREERDP_API int tls_write_all(rdpTls* tls, BYTE* data, int length);
FREERDP_API int tls_wait_read(rdpTls* tls);
FREERDP_API int tls_wait_write(rdpTls* tls);
+FREERDP_API BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname);
FREERDP_API BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname);
FREERDP_API void tls_print_certificate_error(char* hostname, char* fingerprint, char* hosts_file);
FREERDP_API void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count);
diff --git a/include/freerdp/event.h b/include/freerdp/event.h
index 9db3c2297..64bc80ca4 100644
--- a/include/freerdp/event.h
+++ b/include/freerdp/event.h
@@ -50,12 +50,26 @@ DEFINE_EVENT_END(PanningChange)
DEFINE_EVENT_BEGIN(ScalingFactorChange)
double ScalingFactor;
DEFINE_EVENT_END(ScalingFactorChange)
+
+DEFINE_EVENT_BEGIN(LocalResizeWindow)
+ int width;
+ int height;
+DEFINE_EVENT_END(LocalResizeWindow)
DEFINE_EVENT_BEGIN(EmbedWindow)
BOOL embed;
void* handle;
DEFINE_EVENT_END(EmbedWindow)
+DEFINE_EVENT_BEGIN(PanningChange)
+ int XPan;
+ int YPan;
+DEFINE_EVENT_END(PanningChange)
+
+DEFINE_EVENT_BEGIN(ScalingFactorChange)
+ double ScalingFactor;
+DEFINE_EVENT_END(ScalingFactorChange)
+
DEFINE_EVENT_BEGIN(ErrorInfo)
UINT32 code;
DEFINE_EVENT_END(ErrorInfo)
@@ -68,6 +82,20 @@ DEFINE_EVENT_BEGIN(Terminate)
int code;
DEFINE_EVENT_END(Terminate)
+DEFINE_EVENT_BEGIN(ConnectionResult)
+ int result;
+DEFINE_EVENT_END(ConnectionResult)
+
+DEFINE_EVENT_BEGIN(ChannelConnected)
+ const char* name;
+ void* pInterface;
+DEFINE_EVENT_END(ChannelConnected)
+
+DEFINE_EVENT_BEGIN(ChannelDisconnected)
+ const char* name;
+ void* pInterface;
+DEFINE_EVENT_END(ChannelDisconnected)
+
#ifdef __cplusplus
}
#endif
diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h
index 214c2f719..e3ce2bf84 100644
--- a/include/freerdp/freerdp.h
+++ b/include/freerdp/freerdp.h
@@ -66,9 +66,6 @@ typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type);
typedef int (*pSendChannelData)(freerdp* instance, int channelId, BYTE* data, int size);
typedef int (*pReceiveChannelData)(freerdp* instance, int channelId, BYTE* data, int size, int flags, int total_size);
-typedef int (*pOnChannelConnected)(freerdp* instance, const char* name, void* pInterface);
-typedef int (*pOnChannelDisconnected)(freerdp* instance, const char* name, void* pInterface);
-
/**
* Defines the context for a given instance of RDP connection.
* It is embedded in the rdp_freerdp structure, and allocated by a call to freerdp_context_new().
@@ -208,9 +205,6 @@ struct rdp_freerdp
This is called by freerdp_channel_process() (if not NULL).
Clients will typically use a function that calls freerdp_channels_data() to perform the needed tasks. */
- ALIGN64 pOnChannelConnected OnChannelConnected;
- ALIGN64 pOnChannelDisconnected OnChannelDisconnected;
-
UINT64 paddingE[80 - 66]; /* 66 */
};
diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h
index b6f34e6f7..b9ca69342 100644
--- a/include/freerdp/settings.h
+++ b/include/freerdp/settings.h
@@ -633,6 +633,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_GatewayDomain 1989
#define FreeRDP_GatewayCredentialsSource 1990
#define FreeRDP_GatewayUseSameCredentials 1991
+#define FreeRDP_GatewayEnabled 1992
#define FreeRDP_RemoteApplicationMode 2112
#define FreeRDP_RemoteApplicationName 2113
#define FreeRDP_RemoteApplicationIcon 2114
@@ -1019,7 +1020,7 @@ struct rdp_settings
*/
/* Gateway */
- ALIGN64 BOOL GatewayUsageMethod; /* 1984 */
+ ALIGN64 UINT32 GatewayUsageMethod; /* 1984 */
ALIGN64 UINT32 GatewayPort; /* 1985 */
ALIGN64 char* GatewayHostname; /* 1986 */
ALIGN64 char* GatewayUsername; /* 1987 */
@@ -1027,7 +1028,8 @@ struct rdp_settings
ALIGN64 char* GatewayDomain; /* 1989 */
ALIGN64 UINT32 GatewayCredentialsSource; /* 1990 */
ALIGN64 BOOL GatewayUseSameCredentials; /* 1991 */
- UINT64 padding2048[2048 - 1992]; /* 1992 */
+ ALIGN64 BOOL GatewayEnabled; /* 1992 */
+ UINT64 padding2048[2048 - 1993]; /* 1993 */
UINT64 padding2112[2112 - 2048]; /* 2048 */
/**
diff --git a/include/freerdp/utils/stopwatch.h b/include/freerdp/utils/stopwatch.h
index 843d1bd12..af6aa1ee3 100644
--- a/include/freerdp/utils/stopwatch.h
+++ b/include/freerdp/utils/stopwatch.h
@@ -20,17 +20,15 @@
#ifndef FREERDP_UTILS_STOPWATCH_H
#define FREERDP_UTILS_STOPWATCH_H
-#include
-
#include
#include
struct _STOPWATCH
{
- clock_t start;
- clock_t end;
- double elapsed;
- clock_t count;
+ UINT64 start;
+ UINT64 end;
+ UINT64 elapsed;
+ UINT32 count;
};
typedef struct _STOPWATCH STOPWATCH;
diff --git a/libfreerdp/cache/glyph.c b/libfreerdp/cache/glyph.c
index 847ac3849..14f2f69dd 100644
--- a/libfreerdp/cache/glyph.c
+++ b/libfreerdp/cache/glyph.c
@@ -500,6 +500,7 @@ void glyph_cache_free(rdpGlyphCache* glyph_cache)
Glyph_Free(glyph_cache->context, glyph);
free(glyph->aj);
free(glyph);
+ glyph_cache->glyphCache[i].entries[j] = NULL;
}
}
free(glyph_cache->glyphCache[i].entries);
@@ -509,6 +510,7 @@ void glyph_cache_free(rdpGlyphCache* glyph_cache)
{
fragment = glyph_cache->fragCache.entries[i].fragment;
free(fragment);
+ glyph_cache->fragCache.entries[i].fragment = NULL;
}
free(glyph_cache->fragCache.entries);
diff --git a/libfreerdp/cache/pointer.c b/libfreerdp/cache/pointer.c
index 484c2985b..57bc3a4ef 100644
--- a/libfreerdp/cache/pointer.c
+++ b/libfreerdp/cache/pointer.c
@@ -68,9 +68,18 @@ void update_pointer_color(rdpContext* context, POINTER_COLOR_UPDATE* pointer_col
pointer->height = pointer_color->height;
pointer->lengthAndMask = pointer_color->lengthAndMask;
pointer->lengthXorMask = pointer_color->lengthXorMask;
- pointer->xorMaskData = pointer_color->xorMaskData;
- pointer->andMaskData = pointer_color->andMaskData;
+ if (pointer->lengthAndMask && pointer_color->xorMaskData)
+ {
+ pointer->andMaskData = (BYTE*) malloc(pointer->lengthAndMask);
+ CopyMemory(pointer->andMaskData, pointer_color->andMaskData, pointer->lengthAndMask);
+ }
+
+ if (pointer->lengthXorMask && pointer_color->xorMaskData)
+ {
+ pointer->xorMaskData = (BYTE*) malloc(pointer->lengthXorMask);
+ CopyMemory(pointer->xorMaskData, pointer_color->xorMaskData, pointer->lengthXorMask);
+ }
pointer->New(context, pointer);
pointer_cache_put(cache->pointer, pointer_color->cacheIndex, pointer);
Pointer_Set(context, pointer);
@@ -202,7 +211,10 @@ void pointer_cache_free(rdpPointerCache* pointer_cache)
pointer = pointer_cache->entries[i];
if (pointer != NULL)
+ {
Pointer_Free(pointer_cache->update->context, pointer);
+ pointer_cache->entries[i] = NULL;
+ }
}
free(pointer_cache->entries);
diff --git a/libfreerdp/codec/CMakeLists.txt b/libfreerdp/codec/CMakeLists.txt
index 8895848b2..19533017b 100644
--- a/libfreerdp/codec/CMakeLists.txt
+++ b/libfreerdp/codec/CMakeLists.txt
@@ -20,9 +20,10 @@ set(MODULE_PREFIX "FREERDP_CODEC")
set(${MODULE_PREFIX}_SRCS
dsp.c
- bitmap.c
color.c
audio.c
+ bitmap_decode.c
+ bitmap_encode.c
rfx_bitstream.h
rfx_constants.h
rfx_decode.c
diff --git a/libfreerdp/codec/bitmap.c b/libfreerdp/codec/bitmap_decode.c
similarity index 99%
rename from libfreerdp/codec/bitmap.c
rename to libfreerdp/codec/bitmap_decode.c
index 598017081..431a213a8 100644
--- a/libfreerdp/codec/bitmap.c
+++ b/libfreerdp/codec/bitmap_decode.c
@@ -1,6 +1,6 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
- * Compressed Bitmap
+ * Bitmap Decompression
*
* Copyright 2011 Jay Sorg
*
diff --git a/libfreerdp/codec/bitmap_encode.c b/libfreerdp/codec/bitmap_encode.c
new file mode 100644
index 000000000..5cdca0b93
--- /dev/null
+++ b/libfreerdp/codec/bitmap_encode.c
@@ -0,0 +1,1574 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Bitmap Compression
+ *
+ * Copyright 2004-2012 Jay Sorg
+ *
+ * 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
+
+#define GETPIXEL8(d, x, y, w) (*(((unsigned char*)d) + ((y) * (w) + (x))))
+#define GETPIXEL16(d, x, y, w) (*(((unsigned short*)d) + ((y) * (w) + (x))))
+#define GETPIXEL32(d, x, y, w) (*(((unsigned int*)d) + ((y) * (w) + (x))))
+
+/*****************************************************************************/
+#define IN_PIXEL8(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \
+ { \
+ if (in_ptr == 0) \
+ { \
+ in_pixel = 0; \
+ } \
+ else if (in_x < in_w) \
+ { \
+ in_pixel = GETPIXEL8(in_ptr, in_x, in_y, in_w); \
+ } \
+ else \
+ { \
+ in_pixel = in_last_pixel; \
+ } \
+ }
+
+/*****************************************************************************/
+#define IN_PIXEL16(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \
+ { \
+ if (in_ptr == 0) \
+ { \
+ in_pixel = 0; \
+ } \
+ else if (in_x < in_w) \
+ { \
+ in_pixel = GETPIXEL16(in_ptr, in_x, in_y, in_w); \
+ } \
+ else \
+ { \
+ in_pixel = in_last_pixel; \
+ } \
+ }
+
+/*****************************************************************************/
+#define IN_PIXEL32(in_ptr, in_x, in_y, in_w, in_last_pixel, in_pixel); \
+ { \
+ if (in_ptr == 0) \
+ { \
+ in_pixel = 0; \
+ } \
+ else if (in_x < in_w) \
+ { \
+ in_pixel = GETPIXEL32(in_ptr, in_x, in_y, in_w); \
+ } \
+ else \
+ { \
+ in_pixel = in_last_pixel; \
+ } \
+ }
+
+/*****************************************************************************/
+/* color */
+#define OUT_COLOR_COUNT1(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x3 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_data); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x60); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_data); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf3); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write_UINT8(in_s, in_data); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* color */
+#define OUT_COLOR_COUNT2(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x3 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT16(in_s, in_data); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x60); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT16(in_s, in_data); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf3); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write_UINT16(in_s, in_data); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* color */
+#define OUT_COLOR_COUNT3(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x3 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_data & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 16) & 0xFF); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x60); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_data & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 16) & 0xFF); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf3); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write_UINT8(in_s, in_data & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_data >> 16) & 0xFF); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* copy */
+#define OUT_COPY_COUNT1(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x4 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, Stream_Buffer(in_data), in_count); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x80); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, Stream_Buffer(in_data), in_count); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf4); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write(in_s, Stream_Buffer(in_data), in_count); \
+ } \
+ } \
+ in_count = 0; \
+ Stream_SetPosition(in_data, 0); \
+ }
+
+/*****************************************************************************/
+/* copy */
+#define OUT_COPY_COUNT2(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x4 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ temp = in_count * 2; \
+ Stream_Write(in_s, Stream_Buffer(in_data), temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x80); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ temp = in_count * 2; \
+ Stream_Write(in_s, Stream_Buffer(in_data), temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf4); \
+ Stream_Write_UINT16(in_s, in_count); \
+ temp = in_count * 2; \
+ Stream_Write(in_s, Stream_Buffer(in_data), temp); \
+ } \
+ } \
+ in_count = 0; \
+ Stream_SetPosition(in_data, 0); \
+ }
+
+/*****************************************************************************/
+/* copy */
+#define OUT_COPY_COUNT3(in_count, in_s, in_data) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x4 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ temp = in_count * 3; \
+ Stream_Write(in_s, Stream_Pointer(in_data), temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x80); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ temp = in_count * 3; \
+ Stream_Write(in_s, Stream_Pointer(in_data), temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf4); \
+ Stream_Write_UINT16(in_s, in_count); \
+ temp = in_count * 3; \
+ Stream_Write(in_s, Stream_Pointer(in_data), temp); \
+ } \
+ } \
+ in_count = 0; \
+ Stream_SetPosition(in_data, 0); \
+ }
+
+/*****************************************************************************/
+/* bicolor */
+#define OUT_BICOLOR_COUNT1(in_count, in_s, in_color1, in_color2) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count / 2 < 16) \
+ { \
+ temp = (0xe << 4) | (in_count / 2); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1); \
+ Stream_Write_UINT8(in_s, in_color2); \
+ } \
+ else if (in_count / 2 < 256 + 16) \
+ { \
+ Stream_Write_UINT8(in_s, 0xe0); \
+ temp = in_count / 2 - 16; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1); \
+ Stream_Write_UINT8(in_s, in_color2); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf8); \
+ temp = in_count / 2; \
+ Stream_Write_UINT16(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1); \
+ Stream_Write_UINT8(in_s, in_color2); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* bicolor */
+#define OUT_BICOLOR_COUNT2(in_count, in_s, in_color1, in_color2) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count / 2 < 16) \
+ { \
+ temp = (0xe << 4) | (in_count / 2); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT16(in_s, in_color1); \
+ Stream_Write_UINT16(in_s, in_color2); \
+ } \
+ else if (in_count / 2 < 256 + 16) \
+ { \
+ Stream_Write_UINT8(in_s, 0xe0); \
+ temp = in_count / 2 - 16; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT16(in_s, in_color1); \
+ Stream_Write_UINT16(in_s, in_color2); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf8); \
+ temp = in_count / 2; \
+ Stream_Write_UINT16(in_s, temp); \
+ Stream_Write_UINT16(in_s, in_color1); \
+ Stream_Write_UINT16(in_s, in_color2); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* bicolor */
+#define OUT_BICOLOR_COUNT3(in_count, in_s, in_color1, in_color2) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count / 2 < 16) \
+ { \
+ temp = (0xe << 4) | (in_count / 2); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 16) & 0xFF); \
+ Stream_Write_UINT8(in_s, in_color2 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 16) & 0xFF); \
+ } \
+ else if (in_count / 2 < 256 + 16) \
+ { \
+ Stream_Write_UINT8(in_s, 0xe0); \
+ temp = in_count / 2 - 16; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 16) & 0xFF); \
+ Stream_Write_UINT8(in_s, in_color2 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 16) & 0xFF); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf8); \
+ temp = in_count / 2; \
+ Stream_Write_UINT16(in_s, temp); \
+ Stream_Write_UINT8(in_s, in_color1 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color1 >> 16) & 0xFF); \
+ Stream_Write_UINT8(in_s, in_color2 & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 8) & 0xFF); \
+ Stream_Write_UINT8(in_s, (in_color2 >> 16) & 0xFF); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fill */
+#define OUT_FILL_COUNT1(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ Stream_Write_UINT8(in_s, in_count); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x0); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf0); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fill */
+#define OUT_FILL_COUNT2(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ Stream_Write_UINT8(in_s, in_count); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x0); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf0); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fill */
+#define OUT_FILL_COUNT3(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ Stream_Write_UINT8(in_s, in_count); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x0); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf0); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* mix */
+#define OUT_MIX_COUNT1(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x1 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x20); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf1); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* mix */
+#define OUT_MIX_COUNT2(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x1 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x20); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf1); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* mix */
+#define OUT_MIX_COUNT3(in_count, in_s) \
+ { \
+ if (in_count > 0) \
+ { \
+ if (in_count < 32) \
+ { \
+ temp = (0x1 << 5) | in_count; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else if (in_count < 256 + 32) \
+ { \
+ Stream_Write_UINT8(in_s, 0x20); \
+ temp = in_count - 32; \
+ Stream_Write_UINT8(in_s, temp); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf1); \
+ Stream_Write_UINT16(in_s, in_count); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fom */
+#define OUT_FOM_COUNT1(in_count, in_s, in_mask, in_mask_len) \
+ { \
+ if (in_count > 0) \
+ { \
+ if ((in_count % 8) == 0 && in_count < 249) \
+ { \
+ temp = (0x2 << 5) | (in_count / 8); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else if (in_count < 256) \
+ { \
+ Stream_Write_UINT8(in_s, 0x40); \
+ temp = in_count - 1; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf2); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fom */
+#define OUT_FOM_COUNT2(in_count, in_s, in_mask, in_mask_len) \
+ { \
+ if (in_count > 0) \
+ { \
+ if ((in_count % 8) == 0 && in_count < 249) \
+ { \
+ temp = (0x2 << 5) | (in_count / 8); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else if (in_count < 256) \
+ { \
+ Stream_Write_UINT8(in_s, 0x40); \
+ temp = in_count - 1; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf2); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+/* fill or mix (fom) */
+#define OUT_FOM_COUNT3(in_count, in_s, in_mask, in_mask_len) \
+ { \
+ if (in_count > 0) \
+ { \
+ if ((in_count % 8) == 0 && in_count < 249) \
+ { \
+ temp = (0x2 << 5) | (in_count / 8); \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else if (in_count < 256) \
+ { \
+ Stream_Write_UINT8(in_s, 0x40); \
+ temp = in_count - 1; \
+ Stream_Write_UINT8(in_s, temp); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ else \
+ { \
+ Stream_Write_UINT8(in_s, 0xf2); \
+ Stream_Write_UINT16(in_s, in_count); \
+ Stream_Write(in_s, in_mask, in_mask_len); \
+ } \
+ } \
+ in_count = 0; \
+ }
+
+/*****************************************************************************/
+#define TEST_FILL \
+ ((last_line == 0 && pixel == 0) || \
+ (last_line != 0 && pixel == ypixel))
+#define TEST_MIX \
+ ((last_line == 0 && pixel == mix) || \
+ (last_line != 0 && pixel == (ypixel ^ mix)))
+#define TEST_FOM (TEST_FILL || TEST_MIX)
+#define TEST_COLOR (pixel == last_pixel)
+#define TEST_BICOLOR \
+ ( \
+ (pixel != last_pixel) && \
+ ( \
+ (!bicolor_spin && pixel == bicolor1 && last_pixel == bicolor2) || \
+ (bicolor_spin && pixel == bicolor2 && last_pixel == bicolor1) \
+ ) \
+ )
+#define RESET_COUNTS \
+ { \
+ bicolor_count = 0; \
+ fill_count = 0; \
+ color_count = 0; \
+ mix_count = 0; \
+ fom_count = 0; \
+ fom_mask_len = 0; \
+ bicolor_spin = 0; \
+ }
+
+/*****************************************************************************/
+int freerdp_bitmap_compress(char* in_data, int width, int height,
+ wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e)
+{
+ char *line;
+ char *last_line;
+ char fom_mask[8192]; /* good for up to 64K bitmap */
+ int lines_sent;
+ int pixel;
+ int count;
+ int color_count;
+ int last_pixel;
+ int bicolor_count;
+ int bicolor1;
+ int bicolor2;
+ int bicolor_spin;
+ int end;
+ int i;
+ int out_count;
+ int ypixel;
+ int last_ypixel;
+ int fill_count;
+ int mix_count;
+ int mix;
+ int fom_count;
+ int fom_mask_len;
+ int temp; /* used in macros */
+
+ Stream_SetPosition(temp_s, 0);
+ fom_mask_len = 0;
+ last_line = 0;
+ lines_sent = 0;
+ end = width + e;
+ count = 0;
+ color_count = 0;
+ last_pixel = 0;
+ last_ypixel = 0;
+ bicolor_count = 0;
+ bicolor1 = 0;
+ bicolor2 = 0;
+ bicolor_spin = 0;
+ fill_count = 0;
+ mix_count = 0;
+ fom_count = 0;
+
+ if (bpp == 8)
+ {
+ mix = 0xFF;
+ out_count = end;
+ line = in_data + width * start_line;
+
+ while (start_line >= 0 && out_count < 32768)
+ {
+ i = Stream_GetPosition(s) + count;
+
+ if (i - color_count >= byte_limit &&
+ i - bicolor_count >= byte_limit &&
+ i - fill_count >= byte_limit &&
+ i - mix_count >= byte_limit &&
+ i - fom_count >= byte_limit)
+ {
+ break;
+ }
+
+ out_count += end;
+
+ for (i = 0; i < end; i++)
+ {
+ /* read next pixel */
+ IN_PIXEL8(line, i, 0, width, last_pixel, pixel);
+ IN_PIXEL8(last_line, i, 0, width, last_ypixel, ypixel);
+
+ if (!TEST_FILL)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FILL_COUNT1(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+ }
+
+ if (!TEST_MIX)
+ {
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_MIX_COUNT1(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+ }
+
+ if (!TEST_COLOR)
+ {
+ if (color_count > 3 &&
+ color_count >= fill_count &&
+ color_count >= bicolor_count &&
+ color_count >= mix_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_COLOR_COUNT1(color_count, s, last_pixel);
+ RESET_COUNTS;
+ }
+
+ color_count = 0;
+ }
+
+ if (!TEST_BICOLOR)
+ {
+ if (bicolor_count > 3 &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ RESET_COUNTS;
+ }
+
+ bicolor_count = 0;
+ bicolor1 = last_pixel;
+ bicolor2 = pixel;
+ bicolor_spin = 0;
+ }
+
+ if (!TEST_FOM)
+ {
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ if (TEST_FILL)
+ {
+ fill_count++;
+ }
+
+ if (TEST_MIX)
+ {
+ mix_count++;
+ }
+
+ if (TEST_COLOR)
+ {
+ color_count++;
+ }
+
+ if (TEST_BICOLOR)
+ {
+ bicolor_spin = !bicolor_spin;
+ bicolor_count++;
+ }
+
+ if (TEST_FOM)
+ {
+ if ((fom_count % 8) == 0)
+ {
+ fom_mask[fom_mask_len] = 0;
+ fom_mask_len++;
+ }
+
+ if (pixel == (ypixel ^ mix))
+ {
+ fom_mask[fom_mask_len - 1] |= (1 << (fom_count % 8));
+ }
+
+ fom_count++;
+ }
+
+ Stream_Write_UINT8(temp_s, pixel);
+ count++;
+ last_pixel = pixel;
+ last_ypixel = ypixel;
+ }
+
+ /* can't take fix, mix, or fom past first line */
+ if (last_line == 0)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FILL_COUNT1(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_MIX_COUNT1(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ last_line = line;
+ line = line - width;
+ start_line--;
+ lines_sent++;
+ }
+
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FILL_COUNT1(fill_count, s);
+ }
+ else if (mix_count > 3 &&
+ mix_count >= color_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= fill_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_MIX_COUNT1(mix_count, s);
+ }
+ else if (color_count > 3 &&
+ color_count >= mix_count &&
+ color_count >= bicolor_count &&
+ color_count >= fill_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_COLOR_COUNT1(color_count, s, last_pixel);
+ }
+ else if (bicolor_count > 3 &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ count -= bicolor_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_BICOLOR_COUNT1(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else if (fom_count > 3 &&
+ fom_count >= mix_count &&
+ fom_count >= color_count &&
+ fom_count >= fill_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT1(count, s, temp_s);
+ OUT_FOM_COUNT1(fom_count, s, fom_mask, fom_mask_len);
+ }
+ else
+ {
+ OUT_COPY_COUNT1(count, s, temp_s);
+ }
+ }
+ else if ((bpp == 15) || (bpp == 16))
+ {
+ mix = (bpp == 15) ? 0xBA1F : 0xFFFF;
+ out_count = end * 2;
+ line = in_data + width * start_line * 2;
+
+ while (start_line >= 0 && out_count < 32768)
+ {
+ i = Stream_GetPosition(s) + count * 2;
+
+ if (i - (color_count * 2) >= byte_limit &&
+ i - (bicolor_count * 2) >= byte_limit &&
+ i - (fill_count * 2) >= byte_limit &&
+ i - (mix_count * 2) >= byte_limit &&
+ i - (fom_count * 2) >= byte_limit)
+ {
+ break;
+ }
+
+ out_count += end * 2;
+
+ for (i = 0; i < end; i++)
+ {
+ /* read next pixel */
+ IN_PIXEL16(line, i, 0, width, last_pixel, pixel);
+ IN_PIXEL16(last_line, i, 0, width, last_ypixel, ypixel);
+
+ if (!TEST_FILL)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FILL_COUNT2(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+ }
+
+ if (!TEST_MIX)
+ {
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_MIX_COUNT2(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+ }
+
+ if (!TEST_COLOR)
+ {
+ if (color_count > 3 &&
+ color_count >= fill_count &&
+ color_count >= bicolor_count &&
+ color_count >= mix_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_COLOR_COUNT2(color_count, s, last_pixel);
+ RESET_COUNTS;
+ }
+
+ color_count = 0;
+ }
+
+ if (!TEST_BICOLOR)
+ {
+ if (bicolor_count > 3 &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ RESET_COUNTS;
+ }
+
+ bicolor_count = 0;
+ bicolor1 = last_pixel;
+ bicolor2 = pixel;
+ bicolor_spin = 0;
+ }
+
+ if (!TEST_FOM)
+ {
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ if (TEST_FILL)
+ {
+ fill_count++;
+ }
+
+ if (TEST_MIX)
+ {
+ mix_count++;
+ }
+
+ if (TEST_COLOR)
+ {
+ color_count++;
+ }
+
+ if (TEST_BICOLOR)
+ {
+ bicolor_spin = !bicolor_spin;
+ bicolor_count++;
+ }
+
+ if (TEST_FOM)
+ {
+ if ((fom_count % 8) == 0)
+ {
+ fom_mask[fom_mask_len] = 0;
+ fom_mask_len++;
+ }
+
+ if (pixel == (ypixel ^ mix))
+ {
+ fom_mask[fom_mask_len - 1] |= (1 << (fom_count % 8));
+ }
+
+ fom_count++;
+ }
+
+ Stream_Write_UINT16(temp_s, pixel);
+ count++;
+ last_pixel = pixel;
+ last_ypixel = ypixel;
+ }
+
+ /* can't take fix, mix, or fom past first line */
+ if (last_line == 0)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FILL_COUNT2(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_MIX_COUNT2(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ last_line = line;
+ line = line - width * 2;
+ start_line--;
+ lines_sent++;
+ }
+
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FILL_COUNT2(fill_count, s);
+ }
+ else if (mix_count > 3 &&
+ mix_count >= color_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= fill_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_MIX_COUNT2(mix_count, s);
+ }
+ else if (color_count > 3 &&
+ color_count >= mix_count &&
+ color_count >= bicolor_count &&
+ color_count >= fill_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_COLOR_COUNT2(color_count, s, last_pixel);
+ }
+ else if (bicolor_count > 3 &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ count -= bicolor_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else if (fom_count > 3 &&
+ fom_count >= mix_count &&
+ fom_count >= color_count &&
+ fom_count >= fill_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT2(count, s, temp_s);
+ OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
+ }
+ else
+ {
+ OUT_COPY_COUNT2(count, s, temp_s);
+ }
+ }
+ else if (bpp == 24)
+ {
+ mix = 0xFFFFFF;
+ out_count = end * 3;
+ line = in_data + width * start_line * 4;
+
+ while (start_line >= 0 && out_count < 32768)
+ {
+ i = Stream_GetPosition(s) + count * 3;
+
+ if (i - (color_count * 3) >= byte_limit &&
+ i - (bicolor_count * 3) >= byte_limit &&
+ i - (fill_count * 3) >= byte_limit &&
+ i - (mix_count * 3) >= byte_limit &&
+ i - (fom_count * 3) >= byte_limit)
+ {
+ break;
+ }
+
+ out_count += end * 3;
+
+ for (i = 0; i < end; i++)
+ {
+ /* read next pixel */
+ IN_PIXEL32(line, i, 0, width, last_pixel, pixel);
+ IN_PIXEL32(last_line, i, 0, width, last_ypixel, ypixel);
+
+ if (!TEST_FILL)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FILL_COUNT3(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+ }
+
+ if (!TEST_MIX)
+ {
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_MIX_COUNT3(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+ }
+
+ if (!TEST_COLOR)
+ {
+ if (color_count > 3 &&
+ color_count >= fill_count &&
+ color_count >= bicolor_count &&
+ color_count >= mix_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_COLOR_COUNT3(color_count, s, last_pixel);
+ RESET_COUNTS;
+ }
+
+ color_count = 0;
+ }
+
+ if (!TEST_BICOLOR)
+ {
+ if (bicolor_count > 3 &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ RESET_COUNTS;
+ }
+
+ bicolor_count = 0;
+ bicolor1 = last_pixel;
+ bicolor2 = pixel;
+ bicolor_spin = 0;
+ }
+
+ if (!TEST_FOM)
+ {
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ if (TEST_FILL)
+ {
+ fill_count++;
+ }
+
+ if (TEST_MIX)
+ {
+ mix_count++;
+ }
+
+ if (TEST_COLOR)
+ {
+ color_count++;
+ }
+
+ if (TEST_BICOLOR)
+ {
+ bicolor_spin = !bicolor_spin;
+ bicolor_count++;
+ }
+
+ if (TEST_FOM)
+ {
+ if ((fom_count % 8) == 0)
+ {
+ fom_mask[fom_mask_len] = 0;
+ fom_mask_len++;
+ }
+
+ if (pixel == (ypixel ^ mix))
+ {
+ fom_mask[fom_mask_len - 1] |= (1 << (fom_count % 8));
+ }
+
+ fom_count++;
+ }
+
+ Stream_Write_UINT8(temp_s, pixel & 0xff);
+ Stream_Write_UINT8(temp_s, (pixel >> 8) & 0xff);
+ Stream_Write_UINT8(temp_s, (pixel >> 16) & 0xff);
+ count++;
+ last_pixel = pixel;
+ last_ypixel = ypixel;
+ }
+
+ /* can't take fix, mix, or fom past first line */
+ if (last_line == 0)
+ {
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FILL_COUNT3(fill_count, s);
+ RESET_COUNTS;
+ }
+
+ fill_count = 0;
+
+ if (mix_count > 3 &&
+ mix_count >= fill_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= color_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_MIX_COUNT3(mix_count, s);
+ RESET_COUNTS;
+ }
+
+ mix_count = 0;
+
+ if (fom_count > 3 &&
+ fom_count >= fill_count &&
+ fom_count >= color_count &&
+ fom_count >= mix_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len);
+ RESET_COUNTS;
+ }
+
+ fom_count = 0;
+ fom_mask_len = 0;
+ }
+
+ last_line = line;
+ line = line - width * 4;
+ start_line--;
+ lines_sent++;
+ }
+
+ if (fill_count > 3 &&
+ fill_count >= color_count &&
+ fill_count >= bicolor_count &&
+ fill_count >= mix_count &&
+ fill_count >= fom_count)
+ {
+ count -= fill_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FILL_COUNT3(fill_count, s);
+ }
+ else if (mix_count > 3 &&
+ mix_count >= color_count &&
+ mix_count >= bicolor_count &&
+ mix_count >= fill_count &&
+ mix_count >= fom_count)
+ {
+ count -= mix_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_MIX_COUNT3(mix_count, s);
+ }
+ else if (color_count > 3 &&
+ color_count >= mix_count &&
+ color_count >= bicolor_count &&
+ color_count >= fill_count &&
+ color_count >= fom_count)
+ {
+ count -= color_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_COLOR_COUNT3(color_count, s, last_pixel);
+ }
+ else if (bicolor_count > 3 &&
+ bicolor_count >= mix_count &&
+ bicolor_count >= color_count &&
+ bicolor_count >= fill_count &&
+ bicolor_count >= fom_count)
+ {
+ if ((bicolor_count % 2) == 0)
+ {
+ count -= bicolor_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else
+ {
+ bicolor_count--;
+ count -= bicolor_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor2, bicolor1);
+ }
+
+ count -= bicolor_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor1, bicolor2);
+ }
+ else if (fom_count > 3 &&
+ fom_count >= mix_count &&
+ fom_count >= color_count &&
+ fom_count >= fill_count &&
+ fom_count >= bicolor_count)
+ {
+ count -= fom_count;
+ OUT_COPY_COUNT3(count, s, temp_s);
+ OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len);
+ }
+ else
+ {
+ OUT_COPY_COUNT3(count, s, temp_s);
+ }
+ }
+
+ return lines_sent;
+}
diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c
index afd9e5ecc..49a81d26f 100644
--- a/libfreerdp/codec/rfx.c
+++ b/libfreerdp/codec/rfx.c
@@ -45,6 +45,7 @@
#include "rfx_encode.h"
#include "rfx_quantization.h"
#include "rfx_dwt.h"
+#include "rfx_rlgr.h"
#include "rfx_sse2.h"
#include "rfx_neon.h"
@@ -137,6 +138,7 @@ static void rfx_profiler_print(RFX_CONTEXT* context)
PROFILER_PRINT_FOOTER;
}
+
RFX_CONTEXT* rfx_context_new(void)
{
HKEY hKey;
@@ -159,8 +161,8 @@ RFX_CONTEXT* rfx_context_new(void)
/*
* align buffers to 16 byte boundary (needed for SSE/NEON instructions)
*
- * y_r_buffer, cb_g_buffer, cr_b_buffer: 64 * 64 * 4 = 16384 (0x4000)
- * dwt_buffer: 32 * 32 * 2 * 2 * 4 = 16384, maximum sub-band width is 32
+ * y_r_buffer, cb_g_buffer, cr_b_buffer: 64 * 64 * sizeof(INT16) = 8192 (0x2000)
+ * dwt_buffer: 32 * 32 * 2 * 2 * sizeof(INT16) = 8192, maximum sub-band width is 32
*
* Additionally we add 32 bytes (16 in front and 16 at the back of the buffer)
* in order to allow optimized functions (SEE, NEON) to read from positions
@@ -168,7 +170,7 @@ RFX_CONTEXT* rfx_context_new(void)
* performed at the BufferPool_Take function calls in rfx_encode/decode.c.
*/
- context->priv->BufferPool = BufferPool_New(TRUE, 16384 + 32, 16);
+ context->priv->BufferPool = BufferPool_New(TRUE, 8192 + 32, 16);
#ifdef _WIN32
{
@@ -196,6 +198,8 @@ RFX_CONTEXT* rfx_context_new(void)
if (status == ERROR_SUCCESS)
{
+ dwSize = sizeof(dwValue);
+
if (RegQueryValueEx(hKey, _T("UseThreads"), NULL, &dwType, (BYTE*) &dwValue, &dwSize) == ERROR_SUCCESS)
context->priv->UseThreads = dwValue ? 1 : 0;
@@ -237,6 +241,8 @@ RFX_CONTEXT* rfx_context_new(void)
context->quantization_encode = rfx_quantization_encode;
context->dwt_2d_decode = rfx_dwt_2d_decode;
context->dwt_2d_encode = rfx_dwt_2d_encode;
+ context->rlgr_decode = rfx_rlgr_decode;
+ context->rlgr_encode = rfx_rlgr_encode;
RFX_INIT_SIMD(context);
@@ -257,6 +263,9 @@ void rfx_context_free(RFX_CONTEXT* context)
{
CloseThreadpool(context->priv->ThreadPool);
DestroyThreadpoolEnvironment(&context->priv->ThreadPoolEnv);
+#ifdef WITH_PROFILER
+ fprintf(stderr, "\nWARNING: Profiling results probably unusable with multithreaded RemoteFX codec!\n");
+#endif
}
BufferPool_Free(context->priv->BufferPool);
@@ -739,7 +748,10 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa
if (context->priv->UseThreads)
{
for (i = 0; i < message->num_tiles; i++)
+ {
WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE);
+ CloseThreadpoolWork(work_objects[i]);
+ }
free(work_objects);
free(params);
diff --git a/libfreerdp/codec/rfx_decode.c b/libfreerdp/codec/rfx_decode.c
index 960096f1d..ff6161590 100644
--- a/libfreerdp/codec/rfx_decode.c
+++ b/libfreerdp/codec/rfx_decode.c
@@ -103,7 +103,7 @@ static void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantizatio
PROFILER_ENTER(context->priv->prof_rfx_decode_component);
PROFILER_ENTER(context->priv->prof_rfx_rlgr_decode);
- rfx_rlgr_decode(context->mode, data, size, buffer, 4096);
+ context->rlgr_decode(context->mode, data, size, buffer, 4096);
PROFILER_EXIT(context->priv->prof_rfx_rlgr_decode);
PROFILER_ENTER(context->priv->prof_rfx_differential_decode);
@@ -218,8 +218,10 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, wStream* data_in,
Stream_Seek(data_in, cr_size);
}
+ PROFILER_ENTER(context->priv->prof_rfx_ycbcr_to_rgb);
prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16),
pSrcDst, 64 * sizeof(INT16), &roi_64x64);
+ PROFILER_EXIT(context->priv->prof_rfx_ycbcr_to_rgb);
PROFILER_ENTER(context->priv->prof_rfx_decode_format_rgb);
rfx_decode_format_rgb(pSrcDst[0], pSrcDst[1], pSrcDst[2],
diff --git a/libfreerdp/codec/rfx_encode.c b/libfreerdp/codec/rfx_encode.c
index b59570bec..2b758988f 100644
--- a/libfreerdp/codec/rfx_encode.c
+++ b/libfreerdp/codec/rfx_encode.c
@@ -209,7 +209,7 @@ static void rfx_encode_component(RFX_CONTEXT* context, const UINT32* quantizatio
PROFILER_EXIT(context->priv->prof_rfx_differential_encode);
PROFILER_ENTER(context->priv->prof_rfx_rlgr_encode);
- *size = rfx_rlgr_encode(context->mode, data, 4096, buffer, buffer_size);
+ *size = context->rlgr_encode(context->mode, data, 4096, buffer, buffer_size);
PROFILER_EXIT(context->priv->prof_rfx_rlgr_encode);
PROFILER_EXIT(context->priv->prof_rfx_encode_component);
diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c
index 7e12b1400..bceb6a03c 100644
--- a/libfreerdp/common/settings.c
+++ b/libfreerdp/common/settings.c
@@ -562,14 +562,14 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id)
return settings->PlayRemoteFx;
break;
- case FreeRDP_GatewayUsageMethod:
- return settings->GatewayUsageMethod;
- break;
-
case FreeRDP_GatewayUseSameCredentials:
return settings->GatewayUseSameCredentials;
break;
+ case FreeRDP_GatewayEnabled:
+ return settings->GatewayEnabled;
+ break;
+
case FreeRDP_RemoteApplicationMode:
return settings->RemoteApplicationMode;
break;
@@ -1017,14 +1017,14 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
settings->PlayRemoteFx = param;
break;
- case FreeRDP_GatewayUsageMethod:
- settings->GatewayUsageMethod = param;
- break;
-
case FreeRDP_GatewayUseSameCredentials:
settings->GatewayUseSameCredentials = param;
break;
+ case FreeRDP_GatewayEnabled:
+ settings->GatewayEnabled = param;
+ break;
+
case FreeRDP_RemoteApplicationMode:
settings->RemoteApplicationMode = param;
break;
@@ -1207,7 +1207,7 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
EventArgsInit(&e, "freerdp");
e.id = id;
- PubSub_OnParamChange(context->pubSub, context->instance, &e);
+ PubSub_OnParamChange(context->pubSub, context, &e);
return -1;
}
@@ -1256,7 +1256,7 @@ int freerdp_set_param_int(rdpSettings* settings, int id, int param)
EventArgsInit(&e, "freerdp");
e.id = id;
- PubSub_OnParamChange(context->pubSub, context->instance, &e);
+ PubSub_OnParamChange(context->pubSub, context, &e);
return 0;
}
@@ -1417,6 +1417,10 @@ UINT32 freerdp_get_param_uint32(rdpSettings* settings, int id)
return settings->PercentScreen;
break;
+ case FreeRDP_GatewayUsageMethod:
+ return settings->GatewayUsageMethod;
+ break;
+
case FreeRDP_GatewayPort:
return settings->GatewayPort;
break;
@@ -1736,6 +1740,10 @@ int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param)
settings->PercentScreen = param;
break;
+ case FreeRDP_GatewayUsageMethod:
+ settings->GatewayUsageMethod = param;
+ break;
+
case FreeRDP_GatewayPort:
settings->GatewayPort = param;
break;
@@ -1898,7 +1906,7 @@ int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param)
EventArgsInit(&e, "freerdp");
e.id = id;
- PubSub_OnParamChange(context->pubSub, context->instance, &e);
+ PubSub_OnParamChange(context->pubSub, context, &e);
return 0;
}
@@ -1940,7 +1948,7 @@ int freerdp_set_param_uint64(rdpSettings* settings, int id, UINT64 param)
EventArgsInit(&e, "freerdp");
e.id = id;
- PubSub_OnParamChange(context->pubSub, context->instance, &e);
+ PubSub_OnParamChange(context->pubSub, context, &e);
return 0;
}
@@ -2278,7 +2286,48 @@ int freerdp_set_param_string(rdpSettings* settings, int id, char* param)
EventArgsInit(&e, "freerdp");
e.id = id;
- PubSub_OnParamChange(context->pubSub, context->instance, &e);
+ PubSub_OnParamChange(context->pubSub, context, &e);
+
+ return 0;
+}
+
+double freerdp_get_param_double(rdpSettings* settings, int id)
+{
+ switch (id)
+ {
+ case FreeRDP_ScalingFactor:
+ return settings->ScalingFactor;
+ break;
+
+ default:
+ return 0;
+ break;
+ }
+
+ return 0;
+}
+
+int freerdp_set_param_double(rdpSettings* settings, int id, double param)
+{
+ ParamChangeEventArgs e;
+ rdpContext* context = ((freerdp*) settings->instance)->context;
+
+ switch (id)
+ {
+ case FreeRDP_ScalingFactor:
+ settings->ScalingFactor = param;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ settings->settings_modified[id] = 1;
+
+ EventArgsInit(&e, "freerdp");
+ e.id = id;
+ PubSub_OnParamChange(context->pubSub, context, &e);
return 0;
}
diff --git a/libfreerdp/core/activation.c b/libfreerdp/core/activation.c
index 58d80ed82..c64c654dd 100644
--- a/libfreerdp/core/activation.c
+++ b/libfreerdp/core/activation.c
@@ -279,6 +279,14 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
{
UINT16 lengthSourceDescriptor;
+ if (rdp->state == CONNECTION_STATE_ACTIVE)
+ {
+ rdp->deactivation_reactivation = TRUE;
+ }
+ else
+ {
+ rdp->deactivation_reactivation = FALSE;
+ }
/*
* Windows XP can send short DEACTIVATE_ALL PDU that doesn't contain
* the following fields.
diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c
index 2ce41eb11..247494e07 100644
--- a/libfreerdp/core/connection.c
+++ b/libfreerdp/core/connection.c
@@ -75,17 +75,21 @@ BOOL rdp_client_connect(rdpRdp* rdp)
nego_init(rdp->nego);
nego_set_target(rdp->nego, settings->ServerHostname, settings->ServerPort);
- if (settings->GatewayUsageMethod)
+ if (settings->GatewayEnabled)
{
- char* user;
+ char* user;
char* domain;
char* cookie;
- int user_length;
+ int user_length = 0;
int domain_length;
int cookie_length;
- user = settings->Username;
- user_length = strlen(settings->Username);
+
+ if (settings->Username)
+ {
+ user = settings->Username;
+ user_length = strlen(settings->Username);
+ }
if (settings->Domain)
domain = settings->Domain;
@@ -100,8 +104,11 @@ BOOL rdp_client_connect(rdpRdp* rdp)
CopyMemory(cookie, domain, domain_length);
CharUpperBuffA(cookie, domain_length);
cookie[domain_length] = '\\';
- CopyMemory(&cookie[domain_length + 1], user, user_length);
- cookie[cookie_length] = '\0';
+
+ if (settings->Username)
+ CopyMemory(&cookie[domain_length + 1], user, user_length);
+
+ cookie[cookie_length] = '\0';
nego_set_cookie(rdp->nego, cookie);
free(cookie);
@@ -587,8 +594,15 @@ BOOL rdp_client_connect_finalize(rdpRdp* rdp)
return FALSE;
if (!rdp_send_client_control_pdu(rdp, CTRLACTION_REQUEST_CONTROL))
return FALSE;
- if (!rdp_send_client_persistent_key_list_pdu(rdp))
- return FALSE;
+ /**
+ * [MS-RDPBCGR] 2.2.1.17
+ * Client persistent key list must be sent if a bitmap is
+ * stored in persistent bitmap cache or the server has advertised support for bitmap
+ * host cache and a deactivation reactivation sequence is *not* in progress.
+ */
+ if (!rdp->deactivation_reactivation && rdp->settings->BitmapCachePersistEnabled)
+ if (!rdp_send_client_persistent_key_list_pdu(rdp))
+ return FALSE;
if (!rdp_send_client_font_list_pdu(rdp, FONTLIST_FIRST | FONTLIST_LAST))
return FALSE;
diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c
index b8569fc61..872b57e51 100644
--- a/libfreerdp/core/fastpath.c
+++ b/libfreerdp/core/fastpath.c
@@ -209,7 +209,7 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 s
#ifdef WITH_DEBUG_RDP
DEBUG_RDP("recv Fast-Path %s Update (0x%X), length:%d",
- updateCode < ARRAYSIZE(FASTPATH_UPDATETYPE_STRINGS) ? FASTPATH_UPDATETYPE_STRINGS[updateCode] : "???", updateCode, capacity);
+ updateCode < ARRAYSIZE(FASTPATH_UPDATETYPE_STRINGS) ? FASTPATH_UPDATETYPE_STRINGS[updateCode] : "???", updateCode, size);
#endif
switch (updateCode)
diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c
index 7d0c3c0ba..396750081 100644
--- a/libfreerdp/core/freerdp.c
+++ b/libfreerdp/core/freerdp.c
@@ -31,6 +31,7 @@
#include "message.h"
#include
+#include
#include
#include
@@ -55,6 +56,7 @@ BOOL freerdp_connect(freerdp* instance)
rdpRdp* rdp;
rdpSettings* settings;
BOOL status = FALSE;
+ ConnectionResultEventArgs e;
/* We always set the return code to 0 before we start the connect sequence*/
connectErrorCode = 0;
@@ -127,29 +129,31 @@ BOOL freerdp_connect(freerdp* instance)
update = instance->update;
- s = StreamPool_Take(rdp->transport->ReceivePool, 0);
- instance->update->pcap_rfx = pcap_open(settings->PlayRemoteFxFile, FALSE);
+ update->pcap_rfx = pcap_open(settings->PlayRemoteFxFile, FALSE);
- if (update->pcap_rfx)
+ if (!update->pcap_rfx)
+ return FALSE;
+ else
update->play_rfx = TRUE;
-
- while (update->play_rfx && pcap_has_next_record(update->pcap_rfx))
+
+ while (pcap_has_next_record(update->pcap_rfx))
{
+
pcap_get_next_record_header(update->pcap_rfx, &record);
- Stream_EnsureCapacity(s, record.length);
+ s = StreamPool_Take(rdp->transport->ReceivePool, record.length);
record.data = Stream_Buffer(s);
pcap_get_next_record_content(update->pcap_rfx, &record);
+ Stream_SetLength(s,record.length);
Stream_SetPosition(s, 0);
update->BeginPaint(update->context);
- update_recv_surfcmds(update, Stream_Capacity(s), s);
+ update_recv_surfcmds(update, Stream_Length(s) , s);
update->EndPaint(update->context);
+ Stream_Release(s);
}
- Stream_Release(s);
-
return TRUE;
}
}
@@ -166,6 +170,10 @@ BOOL freerdp_connect(freerdp* instance)
SetEvent(rdp->transport->connectedEvent);
+ EventArgsInit(&e, "freerdp");
+ e.result = status ? 0 : -1;
+ PubSub_OnConnectionResult(instance->context->pubSub, instance->context, &e);
+
return status;
}
@@ -322,12 +330,16 @@ static wEventType FreeRDP_Events[] =
{
DEFINE_EVENT_ENTRY(WindowStateChange)
DEFINE_EVENT_ENTRY(ResizeWindow)
+ DEFINE_EVENT_ENTRY(LocalResizeWindow)
DEFINE_EVENT_ENTRY(EmbedWindow)
DEFINE_EVENT_ENTRY(PanningChange)
DEFINE_EVENT_ENTRY(ScalingFactorChange)
DEFINE_EVENT_ENTRY(ErrorInfo)
DEFINE_EVENT_ENTRY(ParamChange)
DEFINE_EVENT_ENTRY(Terminate)
+ DEFINE_EVENT_ENTRY(ConnectionResult)
+ DEFINE_EVENT_ENTRY(ChannelConnected)
+ DEFINE_EVENT_ENTRY(ChannelDisconnected)
};
/** Allocator function for a rdp context.
@@ -394,7 +406,10 @@ void freerdp_context_free(freerdp* instance)
IFCALL(instance->ContextFree, instance, instance->context);
rdp_free(instance->context->rdp);
+ instance->context->rdp = NULL;
+
graphics_free(instance->context->graphics);
+ instance->context->graphics = NULL;
PubSub_Free(instance->context->pubSub);
diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c
index c6bb45dd1..cf013f2d8 100644
--- a/libfreerdp/core/gateway/tsg.c
+++ b/libfreerdp/core/gateway/tsg.c
@@ -1369,6 +1369,10 @@ BOOL tsg_disconnect(rdpTsg* tsg)
* | |
*/
+
+ if (tsg == NULL)
+ return FALSE;
+
tsg->rpc->client->SynchronousReceive = TRUE;
/* if we are already in state pending (i.e. if a server initiated disconnect was issued)
@@ -1392,7 +1396,12 @@ BOOL tsg_disconnect(rdpTsg* tsg)
int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length)
{
int CopyLength;
- rdpRpc* rpc = tsg->rpc;
+ rdpRpc* rpc;
+
+ if (tsg == NULL)
+ return -1;
+
+ rpc = tsg->rpc;
if (tsg->PendingPdu)
{
diff --git a/libfreerdp/core/graphics.c b/libfreerdp/core/graphics.c
index 18b6d05cb..218f10c60 100644
--- a/libfreerdp/core/graphics.c
+++ b/libfreerdp/core/graphics.c
@@ -117,10 +117,16 @@ void Pointer_Free(rdpContext* context, rdpPointer* pointer)
pointer->Free(context, pointer);
if (pointer->xorMaskData)
+ {
free(pointer->xorMaskData);
+ pointer->xorMaskData = NULL;
+ }
if (pointer->andMaskData)
+ {
free(pointer->andMaskData);
+ pointer->andMaskData = NULL;
+ }
free(pointer);
}
diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c
index b98d41e9a..ebc462fa5 100644
--- a/libfreerdp/core/license.c
+++ b/libfreerdp/core/license.c
@@ -107,7 +107,7 @@ void license_print_scope_list(SCOPE_LIST* scopeList)
for (index = 0; index < scopeList->count; index++)
{
scope = &scopeList->array[index];
- fprintf(stderr, "\t%s\n", (char*) scope->buffer);
+ fprintf(stderr, "\t%s\n", (char*) scope->data);
}
}
@@ -810,11 +810,11 @@ BOOL license_read_platform_challenge_packet(rdpLicense* license, wStream* s)
fprintf(stderr, "\n");
fprintf(stderr, "EncryptedPlatformChallenge:\n");
- winpr_HexDump(license->EncryptedPlatformChallenge->buffer, license->EncryptedPlatformChallenge->length);
+ winpr_HexDump(license->EncryptedPlatformChallenge->data, license->EncryptedPlatformChallenge->length);
fprintf(stderr, "\n");
fprintf(stderr, "PlatformChallenge:\n");
- winpr_HexDump(license->PlatformChallenge->buffer, license->PlatformChallenge->length);
+ winpr_HexDump(license->PlatformChallenge->data, license->PlatformChallenge->length);
fprintf(stderr, "\n");
fprintf(stderr, "MacData:\n");
@@ -937,13 +937,13 @@ void license_write_new_license_request_packet(rdpLicense* license, wStream* s)
fprintf(stderr, "\n");
fprintf(stderr, "EncryptedPremasterSecret\n");
- winpr_HexDump(license->EncryptedPremasterSecret->buffer, license->EncryptedPremasterSecret->length);
+ winpr_HexDump(license->EncryptedPremasterSecret->data, license->EncryptedPremasterSecret->length);
fprintf(stderr, "\n");
- fprintf(stderr, "ClientUserName (%d): %s\n", license->ClientUserName->length, (char*) license->ClientUserName->buffer);
+ fprintf(stderr, "ClientUserName (%d): %s\n", license->ClientUserName->length, (char*) license->ClientUserName->data);
fprintf(stderr, "\n");
- fprintf(stderr, "ClientMachineName (%d): %s\n", license->ClientMachineName->length, (char*) license->ClientMachineName->buffer);
+ fprintf(stderr, "ClientMachineName (%d): %s\n", license->ClientMachineName->length, (char*) license->ClientMachineName->data);
fprintf(stderr, "\n");
#endif
}
@@ -1048,7 +1048,7 @@ void license_send_platform_challenge_response_packet(rdpLicense* license)
fprintf(stderr, "\n");
fprintf(stderr, "EncryptedHardwareId:\n");
- winpr_HexDump(license->EncryptedHardwareId->buffer, 20);
+ winpr_HexDump(license->EncryptedHardwareId->data, 20);
fprintf(stderr, "\n");
#endif
diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c
index 2b4b71992..875c0ae73 100644
--- a/libfreerdp/core/nla.c
+++ b/libfreerdp/core/nla.c
@@ -1245,6 +1245,7 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTransport* transport, rdpSettings*
ZeroMemory(&credssp->negoToken, sizeof(SecBuffer));
ZeroMemory(&credssp->pubKeyAuth, sizeof(SecBuffer));
ZeroMemory(&credssp->authInfo, sizeof(SecBuffer));
+ SecInvalidateHandle(&credssp->context);
if (credssp->server)
{
diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c
index 3806a736e..eb4ad60ea 100644
--- a/libfreerdp/core/peer.c
+++ b/libfreerdp/core/peer.c
@@ -272,6 +272,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
sspi_CopyAuthIdentity(&client->identity, &(rdp->nego->transport->credssp->identity));
IFCALLRET(client->Logon, client->authenticated, client, &client->identity, TRUE);
credssp_free(rdp->nego->transport->credssp);
+ rdp->nego->transport->credssp = NULL;
}
else
{
diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h
index a0f2c9530..fc730261e 100644
--- a/libfreerdp/core/rdp.h
+++ b/libfreerdp/core/rdp.h
@@ -157,6 +157,7 @@ struct rdp_rdp
UINT32 finalize_sc_pdus;
BOOL disconnect;
BOOL resendFocus;
+ BOOL deactivation_reactivation;
};
BOOL rdp_read_security_header(wStream* s, UINT16* flags);
diff --git a/libfreerdp/core/surface.c b/libfreerdp/core/surface.c
index 3de41339f..7d0fb229a 100644
--- a/libfreerdp/core/surface.c
+++ b/libfreerdp/core/surface.c
@@ -58,15 +58,6 @@ static int update_recv_surfcmd_surface_bits(rdpUpdate* update, wStream* s, UINT3
return 0;
}
-static void update_send_frame_acknowledge(rdpRdp* rdp, UINT32 frameId)
-{
- wStream* s;
-
- s = rdp_data_pdu_init(rdp);
- Stream_Write_UINT32(s, frameId);
- rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE, rdp->mcs->user_id);
-}
-
static int update_recv_surfcmd_frame_marker(rdpUpdate* update, wStream* s, UINT32 *length)
{
SURFACE_FRAME_MARKER* marker = &update->surface_frame_marker;
@@ -79,13 +70,6 @@ static int update_recv_surfcmd_frame_marker(rdpUpdate* update, wStream* s, UINT3
IFCALL(update->SurfaceFrameMarker, update->context, marker);
- if (update->context->rdp->settings->ReceivedCapabilities[CAPSET_TYPE_FRAME_ACKNOWLEDGE] &&
- (update->context->rdp->settings->FrameAcknowledge > 0) &&
- (marker->frameAction == SURFACECMD_FRAMEACTION_END))
- {
- update_send_frame_acknowledge(update->context->rdp, marker->frameId);
- }
-
*length = 6;
return 0;
diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c
index a9a710511..40885442b 100644
--- a/libfreerdp/core/transport.c
+++ b/libfreerdp/core/transport.c
@@ -159,6 +159,7 @@ BOOL transport_connect_nla(rdpTransport* transport)
"If credentials are valid, the NTLMSSP implementation may be to blame.\n");
credssp_free(transport->credssp);
+ transport->credssp = NULL;
return FALSE;
}
@@ -212,7 +213,7 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 por
(LPTHREAD_START_ROUTINE) transport_client_thread, transport, 0, NULL);
}
- if (transport->settings->GatewayUsageMethod)
+ if (transport->settings->GatewayEnabled)
{
transport->layer = TRANSPORT_LAYER_TSG;
transport->TcpOut = tcp_new(settings);
@@ -292,6 +293,7 @@ BOOL transport_accept_nla(rdpTransport* transport)
{
fprintf(stderr, "client authentication failure\n");
credssp_free(transport->credssp);
+ transport->credssp = NULL;
return FALSE;
}
@@ -786,7 +788,6 @@ static void* transport_client_thread(void* arg)
freerdp* instance;
rdpContext* context;
rdpTransport* transport;
- TerminateEventArgs e;
transport = (rdpTransport*) arg;
instance = (freerdp*) transport->settings->instance;
diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c
index 6b24f178b..c4eaedeec 100644
--- a/libfreerdp/core/update.c
+++ b/libfreerdp/core/update.c
@@ -677,6 +677,7 @@ static void update_send_refresh_rect(rdpContext* context, BYTE count, RECTANGLE_
update_write_refresh_rect(s, count, areas);
rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_REFRESH_RECT, rdp->mcs->user_id);
+ Stream_Release(s);
}
}
@@ -705,6 +706,7 @@ static void update_send_suppress_output(rdpContext* context, BYTE allow, RECTANG
update_write_suppress_output(s, allow, area);
rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SUPPRESS_OUTPUT, rdp->mcs->user_id);
+ Stream_Release(s);
}
}
@@ -717,6 +719,7 @@ static void update_send_surface_command(rdpContext* context, wStream* s)
Stream_EnsureRemainingCapacity(update, Stream_GetPosition(s));
Stream_Write(update, Stream_Buffer(s), Stream_GetPosition(s));
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, update);
+ Stream_Release(update);
}
static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command)
@@ -733,6 +736,8 @@ static void update_send_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND*
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
update_force_flush(context);
+
+ Stream_Release(s);
}
static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker)
@@ -747,6 +752,8 @@ static void update_send_surface_frame_marker(rdpContext* context, SURFACE_FRAME_
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SURFCMDS, s);
update_force_flush(context);
+
+ Stream_Release(s);
}
static void update_send_frame_acknowledge(rdpContext* context, UINT32 frameId)
@@ -759,6 +766,7 @@ static void update_send_frame_acknowledge(rdpContext* context, UINT32 frameId)
s = rdp_data_pdu_init(rdp);
Stream_Write_UINT32(s, frameId);
rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FRAME_ACKNOWLEDGE, rdp->mcs->user_id);
+ Stream_Release(s);
}
}
@@ -770,6 +778,7 @@ static void update_send_synchronize(rdpContext* context)
s = fastpath_update_pdu_init(rdp->fastpath);
Stream_Zero(s, 2); /* pad2Octets (2 bytes) */
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_SYNCHRONIZE, s);
+ Stream_Release(s);
}
static void update_send_desktop_resize(rdpContext* context)
@@ -1311,6 +1320,7 @@ static void update_send_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDAT
updateCode = FASTPATH_UPDATETYPE_PTR_DEFAULT;
fastpath_send_update_pdu(rdp->fastpath, updateCode, s);
+ Stream_Release(s);
}
static void update_write_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color)
@@ -1342,6 +1352,7 @@ static void update_send_pointer_color(rdpContext* context, POINTER_COLOR_UPDATE*
s = fastpath_update_pdu_init(rdp->fastpath);
update_write_pointer_color(s, pointer_color);
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_COLOR, s);
+ Stream_Release(s);
}
static void update_send_pointer_new(rdpContext* context, POINTER_NEW_UPDATE* pointer_new)
@@ -1353,6 +1364,7 @@ static void update_send_pointer_new(rdpContext* context, POINTER_NEW_UPDATE* poi
Stream_Write_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
update_write_pointer_color(s, &pointer_new->colorPtrAttr);
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s);
+ Stream_Release(s);
}
static void update_send_pointer_cached(rdpContext* context, POINTER_CACHED_UPDATE* pointer_cached)
@@ -1363,6 +1375,7 @@ static void update_send_pointer_cached(rdpContext* context, POINTER_CACHED_UPDAT
s = fastpath_update_pdu_init(rdp->fastpath);
Stream_Write_UINT16(s, pointer_cached->cacheIndex); /* cacheIndex (2 bytes) */
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_CACHED, s);
+ Stream_Release(s);
}
BOOL update_read_refresh_rect(rdpUpdate* update, wStream* s)
diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c
index 78b9b637e..0c4bce4c9 100644
--- a/libfreerdp/crypto/tls.c
+++ b/libfreerdp/crypto/tls.c
@@ -100,6 +100,7 @@ BOOL tls_connect(rdpTls* tls)
CryptoCert cert;
long options = 0;
int connection_status;
+ char *hostname;
tls->ctx = SSL_CTX_new(TLSv1_client_method());
@@ -183,7 +184,12 @@ BOOL tls_connect(rdpTls* tls)
return FALSE;
}
- if (!tls_verify_certificate(tls, cert, tls->settings->ServerHostname))
+ if (tls->settings->GatewayEnabled)
+ hostname = tls->settings->GatewayHostname;
+ else
+ hostname = tls->settings->ServerHostname;
+
+ if (!tls_verify_certificate(tls, cert, hostname))
{
fprintf(stderr, "tls_connect: certificate not trusted, aborting.\n");
tls_disconnect(tls);
@@ -513,6 +519,26 @@ BOOL tls_print_error(char* func, SSL* connection, int value)
}
}
+BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname)
+{
+ if (strlen(hostname) == pattern_length)
+ {
+ if (memcmp((void*) hostname, (void*) pattern, pattern_length) == 0)
+ return TRUE;
+ }
+
+ if (pattern_length > 2 && pattern[0] == '*' && pattern[1] == '.' && strlen(hostname) >= pattern_length)
+ {
+ char *check_hostname = &hostname[ strlen(hostname) - pattern_length+1 ];
+ if (memcmp((void*) check_hostname, (void*) &pattern[1], pattern_length - 1) == 0 )
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
{
int match;
@@ -549,11 +575,8 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
if (common_name != NULL)
{
- if (strlen(hostname) == common_name_length)
- {
- if (memcmp((void*) hostname, (void*) common_name, common_name_length) == 0)
- hostname_match = TRUE;
- }
+ if (tls_match_hostname(common_name, common_name_length, hostname))
+ hostname_match = TRUE;
}
/* compare against alternative names */
@@ -562,10 +585,10 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
{
for (index = 0; index < alt_names_count; index++)
{
- if (strlen(hostname) == alt_names_lengths[index])
+ if (tls_match_hostname(alt_names[index], alt_names_lengths[index], hostname))
{
- if (memcmp((void*) hostname, (void*) alt_names[index], alt_names_lengths[index]) == 0)
- hostname_match = TRUE;
+ hostname_match = TRUE;
+ break;
}
}
}
@@ -662,7 +685,8 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
}
#ifndef _WIN32
- free(common_name);
+ if (common_name)
+ free(common_name);
#endif
return verification_status;
@@ -692,25 +716,20 @@ void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name
fprintf(stderr, "@ WARNING: CERTIFICATE NAME MISMATCH! @\n");
fprintf(stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
fprintf(stderr, "The hostname used for this connection (%s) \n", hostname);
-
- if (alt_names_count < 1)
+ fprintf(stderr, "does not match %s given in the certificate:\n", alt_names_count < 1 ? "the name" : "any of the names");
+ fprintf(stderr, "Common Name (CN):\n");
+ fprintf(stderr, "\t%s\n", common_name ? common_name : "no CN found in certificate");
+ if (alt_names_count > 1)
{
- fprintf(stderr, "does not match the name given in the certificate:\n");
- fprintf(stderr, "%s\n", common_name);
- }
- else
- {
- fprintf(stderr, "does not match the names given in the certificate:\n");
- fprintf(stderr, "%s", common_name);
-
- for (index = 0; index < alt_names_count; index++)
+ fprintf(stderr, "Alternative names:\n");
+ if (alt_names_count > 1)
{
- fprintf(stderr, ", %s", alt_names[index]);
+ for (index = 0; index < alt_names_count; index++)
+ {
+ fprintf(stderr, "\t %s\n", alt_names[index]);
+ }
}
-
- fprintf(stderr, "\n");
}
-
fprintf(stderr, "A valid certificate for the wrong name should NOT be trusted!\n");
}
diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c
index 7e64be5e2..6a9cea2f3 100644
--- a/libfreerdp/gdi/gdi.c
+++ b/libfreerdp/gdi/gdi.c
@@ -739,6 +739,28 @@ void gdi_ellipse_cb(rdpContext* context, ELLIPSE_CB_ORDER* ellipse_cb)
fprintf(stderr, "EllipseCB\n");
}
+void gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker)
+{
+ DEBUG_GDI("frameId %d frameAction %d",
+ surface_frame_marker->frameId,
+ surface_frame_marker->frameAction);
+
+ /* TODO: Implement frame marker completely */
+
+ switch (surface_frame_marker->frameAction)
+ {
+ case SURFACECMD_FRAMEACTION_BEGIN:
+ break;
+
+ case SURFACECMD_FRAMEACTION_END:
+ if (context->instance->settings->FrameAcknowledge > 0)
+ {
+ IFCALL(context->instance->update->SurfaceFrameAcknowledge, context, surface_frame_marker->frameId);
+ }
+ break;
+ }
+}
+
int tilenum = 0;
void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command)
@@ -890,6 +912,7 @@ void gdi_register_update_callbacks(rdpUpdate* update)
primary->EllipseCB = gdi_ellipse_cb;
update->SurfaceBits = gdi_surface_bits;
+ update->SurfaceFrameMarker = gdi_surface_frame_marker;
}
void gdi_init_primary(rdpGdi* gdi)
diff --git a/libfreerdp/gdi/graphics.c b/libfreerdp/gdi/graphics.c
index dcc3c46e7..3bd5f2801 100644
--- a/libfreerdp/gdi/graphics.c
+++ b/libfreerdp/gdi/graphics.c
@@ -107,7 +107,7 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
rdpGdi* gdi;
BOOL status;
- size = width * height * (bpp + 7) / 8;
+ size = width * height * ((bpp + 7) / 8);
if (bitmap->data == NULL)
bitmap->data = (BYTE*) malloc(size);
diff --git a/libfreerdp/gdi/test/TestGdiRop3.c b/libfreerdp/gdi/test/TestGdiRop3.c
index 5dec672a7..f33d68feb 100644
--- a/libfreerdp/gdi/test/TestGdiRop3.c
+++ b/libfreerdp/gdi/test/TestGdiRop3.c
@@ -175,7 +175,7 @@ char* gdi_convert_postfix_to_infix(char* postfix)
dl = al + bl + cl + 3;
- d = malloc(cl + 1);
+ d = malloc(dl + 1);
sprintf_s(d, dl, "(%s%s%s)", b ? b : "", c, a);
Stack_Push(stack, d);
diff --git a/libfreerdp/locale/keyboard_xkbfile.c b/libfreerdp/locale/keyboard_xkbfile.c
index 2215e6fc7..8ae0948c3 100644
--- a/libfreerdp/locale/keyboard_xkbfile.c
+++ b/libfreerdp/locale/keyboard_xkbfile.c
@@ -154,6 +154,7 @@ XKB_KEY_NAME_SCANCODE XKB_KEY_NAME_SCANCODE_TABLE[] =
{ "LWIN", RDP_SCANCODE_LWIN},
{ "RWIN", RDP_SCANCODE_RWIN},
{ "COMP", RDP_SCANCODE_APPS},
+ { "MENU", RDP_SCANCODE_APPS}, // WinMenu in xfree86 layout
{ "KPDV", RDP_SCANCODE_DIVIDE}, // KP!
{ "RCTL", RDP_SCANCODE_RCONTROL},
{ "RALT", RDP_SCANCODE_RMENU},
diff --git a/libfreerdp/utils/pcap.c b/libfreerdp/utils/pcap.c
index 4f7f77952..52d912bf3 100644
--- a/libfreerdp/utils/pcap.c
+++ b/libfreerdp/utils/pcap.c
@@ -158,7 +158,7 @@ rdpPcap* pcap_open(char* name, BOOL write)
{
rdpPcap* pcap;
- FILE* pcap_fp = fopen(name, write ? "w+" : "r");
+ FILE* pcap_fp = fopen(name, write ? "w+b" : "rb");
if (pcap_fp == NULL)
{
diff --git a/libfreerdp/utils/profiler.c b/libfreerdp/utils/profiler.c
index f12a25cc9..3d8fae62d 100644
--- a/libfreerdp/utils/profiler.c
+++ b/libfreerdp/utils/profiler.c
@@ -70,7 +70,7 @@ void profiler_print(PROFILER* profiler)
double elapsed_sec = stopwatch_get_elapsed_time_in_seconds(profiler->stopwatch);
double avg_sec = elapsed_sec / (double) profiler->stopwatch->count;
- fprintf(stderr, "| %-30.30s| %'10lu | %'9f | %'9f |\n", profiler->name, profiler->stopwatch->count, elapsed_sec, avg_sec);
+ fprintf(stderr, "| %-30.30s| %10lu | %9f | %9f |\n", profiler->name, profiler->stopwatch->count, elapsed_sec, avg_sec);
}
void profiler_print_footer()
diff --git a/libfreerdp/utils/stopwatch.c b/libfreerdp/utils/stopwatch.c
index a9ffd6bb6..fb1c5c161 100644
--- a/libfreerdp/utils/stopwatch.c
+++ b/libfreerdp/utils/stopwatch.c
@@ -26,9 +26,33 @@
#include
+#ifdef _WIN32
+LARGE_INTEGER stopwatch_freq = { 0, 0 };
+#else
+#include
+#endif
+
+void stopwatch_set_time(UINT64* usecs)
+{
+#ifdef _WIN32
+ LARGE_INTEGER perfcount;
+ QueryPerformanceCounter(&perfcount);
+ *usecs = (perfcount.QuadPart * 1000000) / stopwatch_freq.QuadPart;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ *usecs = tv.tv_sec * 1000000 + tv.tv_usec;
+#endif
+}
+
STOPWATCH* stopwatch_create()
{
STOPWATCH* sw;
+#ifdef _WIN32
+ if (stopwatch_freq.QuadPart == 0) {
+ QueryPerformanceFrequency(&stopwatch_freq);
+ }
+#endif
sw = (STOPWATCH*) malloc(sizeof(STOPWATCH));
stopwatch_reset(sw);
@@ -43,13 +67,13 @@ void stopwatch_free(STOPWATCH* stopwatch)
void stopwatch_start(STOPWATCH* stopwatch)
{
- stopwatch->start = clock();
+ stopwatch_set_time(&stopwatch->start);
stopwatch->count++;
}
void stopwatch_stop(STOPWATCH* stopwatch)
{
- stopwatch->end = clock();
+ stopwatch_set_time(&stopwatch->end);
stopwatch->elapsed += (stopwatch->end - stopwatch->start);
}
@@ -63,22 +87,12 @@ void stopwatch_reset(STOPWATCH* stopwatch)
double stopwatch_get_elapsed_time_in_seconds(STOPWATCH* stopwatch)
{
- return ((double) stopwatch->elapsed) / CLOCKS_PER_SEC;
+ return (stopwatch->elapsed/1000000.0);
}
void stopwatch_get_elapsed_time_in_useconds(STOPWATCH* stopwatch, UINT32* sec, UINT32* usec)
{
- double uelapsed;
- double clocks_per_usec;
-
- *sec = ((UINT32) stopwatch->elapsed) / CLOCKS_PER_SEC;
- uelapsed = stopwatch->elapsed - ((double)(*sec) * CLOCKS_PER_SEC);
-
- clocks_per_usec = (CLOCKS_PER_SEC / 1000000);
-
- if (clocks_per_usec > 0.0)
- *usec = (UINT32)(uelapsed / clocks_per_usec);
- else
- *usec = 0;
+ *sec = stopwatch->elapsed / 1000000;
+ *usec = stopwatch->elapsed % 1000000;
}
diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt
index 265706ba5..fed64d78c 100644
--- a/server/CMakeLists.txt
+++ b/server/CMakeLists.txt
@@ -19,11 +19,11 @@
add_subdirectory(common)
-if(NOT WIN32)
- if(WITH_SAMPLE)
- add_subdirectory(Sample)
- endif()
+if(WITH_SAMPLE)
+ add_subdirectory(Sample)
+endif()
+if(NOT WIN32)
if(WITH_X11)
add_subdirectory(X11)
endif()
diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c
index 5dadbd013..e988a2e70 100644
--- a/server/Sample/sfreerdp.c
+++ b/server/Sample/sfreerdp.c
@@ -26,14 +26,13 @@
#include
#include
#include
-#include
#include
-#include
#include
#include
#include
+#include
#include
#include "sf_audin.h"
@@ -41,6 +40,10 @@
#include "sfreerdp.h"
+#define SAMPLE_SERVER_USE_CLIENT_RESOLUTION 1
+#define SAMPLE_SERVER_DEFAULT_WIDTH 1024
+#define SAMPLE_SERVER_DEFAULT_HEIGHT 768
+
static char* test_pcap_file = NULL;
static BOOL test_dump_rfx_realtime = TRUE;
@@ -48,8 +51,8 @@ void test_peer_context_new(freerdp_peer* client, testPeerContext* context)
{
context->rfx_context = rfx_context_new();
context->rfx_context->mode = RLGR3;
- context->rfx_context->width = client->settings->DesktopWidth;
- context->rfx_context->height = client->settings->DesktopHeight;
+ context->rfx_context->width = SAMPLE_SERVER_DEFAULT_WIDTH;
+ context->rfx_context->height = SAMPLE_SERVER_DEFAULT_HEIGHT;
rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_R8G8B8);
context->nsc_context = nsc_context_new();
@@ -473,6 +476,17 @@ BOOL tf_peer_post_connect(freerdp_peer* client)
printf("Client requested desktop: %dx%dx%d\n",
client->settings->DesktopWidth, client->settings->DesktopHeight, client->settings->ColorDepth);
+#if (SAMPLE_SERVER_USE_CLIENT_RESOLUTION == 1)
+ context->rfx_context->width = client->settings->DesktopWidth;
+ context->rfx_context->height = client->settings->DesktopHeight;
+ printf("Using resolution requested by client.\n");
+#else
+ client->settings->DesktopWidth = context->rfx_context->width;
+ client->settings->DesktopHeight = context->rfx_context->height;
+ printf("Resizing client to %dx%d\n", client->settings->DesktopWidth, client->settings->DesktopHeight);
+ client->update->DesktopResize(client->update->context);
+#endif
+
/* A real server should tag the peer as activated here and start sending updates in main loop. */
test_peer_load_icon(client);
@@ -554,9 +568,11 @@ void tf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
}
else
{
- client->settings->DesktopWidth = 640;
- client->settings->DesktopHeight = 480;
+ client->settings->DesktopWidth = SAMPLE_SERVER_DEFAULT_WIDTH;
+ client->settings->DesktopHeight = SAMPLE_SERVER_DEFAULT_HEIGHT;
}
+ context->rfx_context->width = client->settings->DesktopWidth;
+ context->rfx_context->height = client->settings->DesktopHeight;
update->DesktopResize(update->context);
context->activated = FALSE;
}
@@ -667,6 +683,8 @@ static void* test_peer_mainloop(void* arg)
client->update->RefreshRect = tf_peer_refresh_rect;
client->update->SuppressOutput = tf_peer_suppress_output;
+ client->settings->MultifragMaxRequestSize = 0xFFFFFF; /* FIXME */
+
client->Initialize(client);
context = (testPeerContext*) client->context;
@@ -681,7 +699,11 @@ static void* test_peer_mainloop(void* arg)
printf("Failed to get FreeRDP file descriptor\n");
break;
}
+
+#ifndef _WIN32
+ /* winsock's select() only works with sockets ! */
WTSVirtualChannelManagerGetFileDescriptor(context->vcm, rfds, &rcount);
+#endif
max_fds = 0;
FD_ZERO(&rfds_set);
@@ -701,15 +723,27 @@ static void* test_peer_mainloop(void* arg)
if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1)
{
+#ifdef _WIN32
+ /* error codes set by windows sockets are not made available through errno ! */
+ int wsa_error = WSAGetLastError();
+ if (!((wsa_error == WSAEWOULDBLOCK) ||
+ (wsa_error == WSAEINPROGRESS) ||
+ (wsa_error == WSAEINTR)))
+ {
+ printf("select failed (WSAGetLastError: %d)\n", wsa_error);
+ break;
+ }
+#else
/* these are not really errors */
if (!((errno == EAGAIN) ||
(errno == EWOULDBLOCK) ||
(errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */
{
- printf("select failed\n");
+ printf("select failed (errno: %d)\n", errno);
break;
}
+#endif
}
if (client->CheckFileDescriptor(client) != TRUE)
@@ -730,10 +764,10 @@ static void* test_peer_mainloop(void* arg)
static void test_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
{
- pthread_t th;
-
- pthread_create(&th, 0, test_peer_mainloop, client);
- pthread_detach(th);
+ HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) test_peer_mainloop, (void*) client, 0, NULL);
+ if (hThread != NULL) {
+ CloseHandle(hThread);
+ }
}
static void test_server_mainloop(freerdp_listener* instance)
@@ -800,9 +834,6 @@ int main(int argc, char* argv[])
{
freerdp_listener* instance;
- /* Ignore SIGPIPE, otherwise an SSL_write failure could crash your server */
- signal(SIGPIPE, SIG_IGN);
-
instance = freerdp_listener_new();
instance->PeerAccepted = test_peer_accepted;
@@ -814,12 +845,14 @@ int main(int argc, char* argv[])
test_dump_rfx_realtime = FALSE;
/* Open the server socket and start listening. */
+ freerdp_wsa_startup();
if (instance->Open(instance, NULL, 3389) &&
instance->OpenLocal(instance, "/tmp/tfreerdp-server.0"))
{
/* Entering the server main loop. In a real server the listener can be run in its own thread. */
test_server_mainloop(instance);
}
+ freerdp_wsa_cleanup();
freerdp_listener_free(instance);
diff --git a/server/X11/cli/xfreerdp-server b/server/X11/cli/xfreerdp-server
deleted file mode 100755
index 9e837526b..000000000
Binary files a/server/X11/cli/xfreerdp-server and /dev/null differ
diff --git a/server/X11/xf_cursor.c b/server/X11/xf_cursor.c
index da43d8ed5..00e4abb3c 100644
--- a/server/X11/xf_cursor.c
+++ b/server/X11/xf_cursor.c
@@ -52,5 +52,6 @@ int xf_cursor_init(xfInfo* xfi)
XFixesSelectCursorInput(xfi->display, DefaultRootWindow(xfi->display), XFixesDisplayCursorNotifyMask);
#endif
+
return 0;
}
diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h
index 03d06a9a8..4ef2e3b19 100644
--- a/winpr/include/winpr/collections.h
+++ b/winpr/include/winpr/collections.h
@@ -171,13 +171,39 @@ typedef struct _wDictionary wDictionary;
/* System.Collections.Specialized.ListDictionary */
+typedef struct _wListDictionaryItem wListDictionaryItem;
+
+struct _wListDictionaryItem
+{
+ void* key;
+ void* value;
+
+ wListDictionaryItem* next;
+};
+
struct _wListDictionary
{
BOOL synchronized;
HANDLE mutex;
+
+ wListDictionaryItem* head;
};
typedef struct _wListDictionary wListDictionary;
+WINPR_API int ListDictionary_Count(wListDictionary* listDictionary);
+
+WINPR_API void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value);
+WINPR_API void ListDictionary_Remove(wListDictionary* listDictionary, void* key);
+WINPR_API void ListDictionary_Clear(wListDictionary* listDictionary);
+
+WINPR_API BOOL ListDictionary_Contains(wListDictionary* listDictionary, void* key);
+
+WINPR_API void* ListDictionary_GetItemValue(wListDictionary* listDictionary, void* key);
+WINPR_API BOOL ListDictionary_SetItemValue(wListDictionary* listDictionary, void* key, void* value);
+
+WINPR_API wListDictionary* ListDictionary_New(BOOL synchronized);
+WINPR_API void ListDictionary_Free(wListDictionary* listDictionary);
+
/* System.Collections.Generic.KeyValuePair */
struct _wKeyValuePair
diff --git a/winpr/include/winpr/platform.h b/winpr/include/winpr/platform.h
index 63d1328b1..f178b0c95 100644
--- a/winpr/include/winpr/platform.h
+++ b/winpr/include/winpr/platform.h
@@ -128,6 +128,22 @@
/* Windows (_WIN32) */
+/* WinRT (_WINRT) */
+
+#if defined(WINAPI_FAMILY)
+#if (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+#ifndef _WINRT
+#define _WINRT 1
+#endif
+#endif
+#endif
+
+#if defined(__cplusplus_winrt)
+#ifndef _WINRT
+#define _WINRT 1
+#endif
+#endif
+
/* Linux (__linux__) */
#if defined(linux) || defined(__linux)
diff --git a/winpr/libwinpr/crt/alignment.c b/winpr/libwinpr/crt/alignment.c
index 765b3d484..1ee3d3850 100644
--- a/winpr/libwinpr/crt/alignment.c
+++ b/winpr/libwinpr/crt/alignment.c
@@ -35,32 +35,20 @@
#include
#endif
+struct _aligned_meminfo {
+ size_t size;
+ void *base_addr;
+};
+
+
void* _aligned_malloc(size_t size, size_t alignment)
{
- void* memptr;
-
- /* alignment must be a power of 2 */
-
- if (alignment % 2 == 1)
- return NULL;
-
-#ifdef ANDROID
- memptr = memalign(alignment, size);
-#else
- if (posix_memalign(&memptr, alignment, size) != 0)
- return NULL;
-#endif
-
- return memptr;
+ return _aligned_offset_malloc(size, alignment, 0);
}
void* _aligned_realloc(void* memblock, size_t size, size_t alignment)
{
- void* memptr = NULL;
-
- memptr = realloc(memblock, size);
-
- return memptr;
+ return _aligned_offset_realloc(memblock, size, alignment, 0);
}
void* _aligned_recalloc(void* memblock, size_t num, size_t size, size_t alignment)
@@ -70,36 +58,59 @@ void* _aligned_recalloc(void* memblock, size_t num, size_t size, size_t alignmen
void* _aligned_offset_malloc(size_t size, size_t alignment, size_t offset)
{
- void* memptr;
+ void* memptr, *tmpptr;
+ struct _aligned_meminfo *ameminfo;
/* alignment must be a power of 2 */
-
if (alignment % 2 == 1)
return NULL;
/* offset must be less than size */
-
if (offset >= size)
return NULL;
/* minimum alignment is pointer size */
-
if (alignment < sizeof(void*))
alignment = sizeof(void*);
-#ifdef ANDROID
- memptr = memalign(alignment, size);
-#else
- if (posix_memalign(&memptr, alignment, size) != 0)
+ /* malloc size + alignment to make sure we can align afterwards */
+ tmpptr = malloc(size + alignment + sizeof(struct _aligned_meminfo));
+ if (!tmpptr)
return NULL;
-#endif
+
+
+ memptr = (void *)((((size_t)((PBYTE)tmpptr + alignment + offset + sizeof(struct _aligned_meminfo)) & ~(alignment - 1)) - offset));
+
+ ameminfo = (struct _aligned_meminfo *) (((size_t)((PBYTE)memptr - sizeof(struct _aligned_meminfo))));
+ ameminfo->base_addr = tmpptr;
+ ameminfo->size = size;
return memptr;
}
void* _aligned_offset_realloc(void* memblock, size_t size, size_t alignment, size_t offset)
{
- return NULL;
+ struct _aligned_meminfo *ameminfo;
+ void *newmem;
+
+ if (!memblock)
+ return _aligned_offset_malloc(size, alignment, offset);
+
+ if (size == 0)
+ {
+ _aligned_free(memblock);
+ return NULL;
+ }
+ /* The following is not very performant but a simple and working solution */
+ newmem = _aligned_offset_malloc(size, alignment, offset);
+
+ if (!newmem)
+ return NULL;
+
+ ameminfo = (struct _aligned_meminfo *) (((size_t)((PBYTE)memblock - sizeof(struct _aligned_meminfo))));
+ memcpy(newmem, memblock, ameminfo->size);
+ _aligned_free(memblock);
+ return newmem;
}
void* _aligned_offset_recalloc(void* memblock, size_t num, size_t size, size_t alignment, size_t offset)
@@ -114,7 +125,13 @@ size_t _aligned_msize(void* memblock, size_t alignment, size_t offset)
void _aligned_free(void* memblock)
{
- free(memblock);
+ struct _aligned_meminfo *ameminfo;
+ if (!memblock)
+ return;
+
+ ameminfo = (struct _aligned_meminfo *) (((size_t)((PBYTE)memblock - sizeof(struct _aligned_meminfo))));
+
+ free(ameminfo->base_addr);
}
#endif
diff --git a/winpr/libwinpr/handle/handle.h b/winpr/libwinpr/handle/handle.h
index 9e9e44a25..75faae4ea 100644
--- a/winpr/libwinpr/handle/handle.h
+++ b/winpr/libwinpr/handle/handle.h
@@ -47,6 +47,9 @@ static inline BOOL winpr_Handle_GetInfo(HANDLE handle, ULONG* pType, PVOID* pObj
{
WINPR_HANDLE* wHandle;
+ if (handle == NULL)
+ return FALSE;
+
wHandle = (WINPR_HANDLE*) handle;
*pType = wHandle->Type;
diff --git a/winpr/libwinpr/sspi/sspi.c b/winpr/libwinpr/sspi/sspi.c
index 8747e3f01..96c959995 100644
--- a/winpr/libwinpr/sspi/sspi.c
+++ b/winpr/libwinpr/sspi/sspi.c
@@ -248,7 +248,7 @@ void* sspi_SecureHandleGetLowerPointer(SecHandle* handle)
{
void* pointer;
- if (!handle)
+ if (!handle || !SecIsValidHandle(handle))
return NULL;
pointer = (void*) ~((size_t) handle->dwLower);
@@ -268,7 +268,7 @@ void* sspi_SecureHandleGetUpperPointer(SecHandle* handle)
{
void* pointer;
- if (!handle)
+ if (!handle || !SecIsValidHandle(handle))
return NULL;
pointer = (void*) ~((size_t) handle->dwUpper);
@@ -839,7 +839,7 @@ SECURITY_STATUS SEC_ENTRY CompleteAuthToken(PCtxtHandle phContext, PSecBufferDes
SECURITY_STATUS SEC_ENTRY DeleteSecurityContext(PCtxtHandle phContext)
{
- char* Name;
+ char* Name = NULL;
SECURITY_STATUS status;
SecurityFunctionTableA* table;
diff --git a/winpr/libwinpr/synch/sleep.c b/winpr/libwinpr/synch/sleep.c
index 9eee1ef8d..096e24323 100644
--- a/winpr/libwinpr/synch/sleep.c
+++ b/winpr/libwinpr/synch/sleep.c
@@ -52,17 +52,23 @@ VOID USleep(DWORD dwMicroseconds)
#ifndef _WIN32
usleep(dwMicroseconds);
#else
- UINT64 t1;
- UINT64 t2;
- UINT64 freq;
+ static LARGE_INTEGER freq = { 0, 0 };
+ LARGE_INTEGER t1 = { 0, 0 };
+ LARGE_INTEGER t2 = { 0, 0 };
- QueryPerformanceCounter((LARGE_INTEGER*) &t1);
- QueryPerformanceCounter((LARGE_INTEGER*) &freq);
+ QueryPerformanceCounter(&t1);
- do
- {
- QueryPerformanceCounter((LARGE_INTEGER*) &t2);
+ if (freq.QuadPart == 0) {
+ QueryPerformanceFrequency(&freq);
}
- while ((t2 - t1) < dwMicroseconds);
+
+ // in order to save cpu cyles we use Sleep() for the large share ...
+ if (dwMicroseconds >= 1000) {
+ Sleep(dwMicroseconds/1000);
+ }
+ // ... and busy loop until all the requested micro seconds have passed
+ do {
+ QueryPerformanceCounter(&t2);
+ } while (((t2.QuadPart - t1.QuadPart)*1000000)/freq.QuadPart < dwMicroseconds);
#endif
}
diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c
index 3006fe246..8060aa8ed 100644
--- a/winpr/libwinpr/synch/wait.c
+++ b/winpr/libwinpr/synch/wait.c
@@ -210,6 +210,9 @@ DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAl
return WAIT_FAILED;
}
+ if (fd == -1)
+ return WAIT_FAILED;
+
FD_SET(fd, &fds);
if (fd > maxfd)
diff --git a/winpr/libwinpr/utils/collections/ListDictionary.c b/winpr/libwinpr/utils/collections/ListDictionary.c
index 2216384a7..d097035ef 100644
--- a/winpr/libwinpr/utils/collections/ListDictionary.c
+++ b/winpr/libwinpr/utils/collections/ListDictionary.c
@@ -26,6 +26,8 @@
/**
* C equivalent of the C# ListDictionary Class:
* http://msdn.microsoft.com/en-us/library/system.collections.specialized.listdictionary.aspx
+ *
+ * Internal implementation uses a singly-linked list
*/
/**
@@ -38,7 +40,21 @@
int ListDictionary_Count(wListDictionary* listDictionary)
{
- return 0;
+ int count = 0;
+ wListDictionaryItem* item;
+
+ if (!listDictionary->head)
+ return 0;
+
+ item = listDictionary->head;
+
+ while (item)
+ {
+ count++;
+ item = item->next;
+ }
+
+ return count;
}
/**
@@ -78,7 +94,28 @@ BOOL ListDictionary_IsSynchronized(wListDictionary* listDictionary)
void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value)
{
+ wListDictionaryItem* item;
+ wListDictionaryItem* lastItem;
+ item = (wListDictionaryItem*) malloc(sizeof(wListDictionaryItem));
+
+ item->key = key;
+ item->value = value;
+
+ item->next = NULL;
+
+ if (!listDictionary->head)
+ {
+ listDictionary->head = item;
+ return;
+ }
+
+ lastItem = listDictionary->head;
+
+ while (lastItem->next)
+ lastItem = lastItem->next;
+
+ lastItem->next = item;
}
/**
@@ -87,7 +124,22 @@ void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value)
void ListDictionary_Clear(wListDictionary* listDictionary)
{
+ wListDictionaryItem* item;
+ wListDictionaryItem* nextItem;
+ if (!listDictionary->head)
+ return;
+
+ item = listDictionary->head;
+
+ while (item)
+ {
+ nextItem = item->next;
+ free(item);
+ item = nextItem;
+ }
+
+ listDictionary->head = NULL;
}
/**
@@ -96,7 +148,22 @@ void ListDictionary_Clear(wListDictionary* listDictionary)
BOOL ListDictionary_Contains(wListDictionary* listDictionary, void* key)
{
- return FALSE;
+ wListDictionaryItem* item;
+
+ if (!listDictionary->head)
+ return FALSE;
+
+ item = listDictionary->head;
+
+ while (item)
+ {
+ if (item->key == key)
+ break;
+
+ item = item->next;
+ }
+
+ return (item) ? TRUE : FALSE;
}
/**
@@ -105,7 +172,89 @@ BOOL ListDictionary_Contains(wListDictionary* listDictionary, void* key)
void ListDictionary_Remove(wListDictionary* listDictionary, void* key)
{
+ wListDictionaryItem* item;
+ wListDictionaryItem* prevItem;
+ if (!listDictionary->head)
+ return;
+
+ item = listDictionary->head;
+
+ if (listDictionary->head->key == key)
+ {
+ listDictionary->head = listDictionary->head->next;
+ free(item);
+ return;
+ }
+
+ if (!item->next)
+ return;
+
+ prevItem = item;
+ item = item->next;
+
+ while (item)
+ {
+ if (item->key == key)
+ {
+ prevItem->next = item->next;
+ free(item);
+ break;
+ }
+
+ item = item->next;
+ }
+}
+
+/**
+ * Get an item value using key
+ */
+
+void* ListDictionary_GetItemValue(wListDictionary* listDictionary, void* key)
+{
+ wListDictionaryItem* item;
+
+ if (!listDictionary->head)
+ return NULL;
+
+ item = listDictionary->head;
+
+ while (item)
+ {
+ if (item->key == key)
+ break;
+
+ item = item->next;
+ }
+
+ return (item) ? item->value : NULL;
+}
+
+/**
+ * Set an item value using key
+ */
+
+BOOL ListDictionary_SetItemValue(wListDictionary* listDictionary, void* key, void* value)
+{
+ wListDictionaryItem* item;
+
+ if (!listDictionary->head)
+ return FALSE;
+
+ item = listDictionary->head;
+
+ while (item)
+ {
+ if (item->key == key)
+ break;
+
+ item = item->next;
+ }
+
+ if (item)
+ item->value = value;
+
+ return (item) ? TRUE : FALSE;
}
/**
@@ -121,6 +270,8 @@ wListDictionary* ListDictionary_New(BOOL synchronized)
if (listDictionary)
{
listDictionary->synchronized = synchronized;
+
+ listDictionary->head = NULL;
}
return listDictionary;
@@ -128,6 +279,10 @@ wListDictionary* ListDictionary_New(BOOL synchronized)
void ListDictionary_Free(wListDictionary* listDictionary)
{
- free(listDictionary);
+ if (listDictionary)
+ {
+ ListDictionary_Clear(listDictionary);
+ free(listDictionary);
+ }
}
diff --git a/winpr/libwinpr/utils/test/CMakeLists.txt b/winpr/libwinpr/utils/test/CMakeLists.txt
index 2656109b0..1455779ef 100644
--- a/winpr/libwinpr/utils/test/CMakeLists.txt
+++ b/winpr/libwinpr/utils/test/CMakeLists.txt
@@ -9,6 +9,7 @@ set(${MODULE_PREFIX}_TESTS
TestPrint.c
TestPubSub.c
TestArrayList.c
+ TestListDictionary.c
TestCmdLine.c
TestStreamPool.c
TestMessageQueue.c
diff --git a/winpr/libwinpr/utils/test/TestListDictionary.c b/winpr/libwinpr/utils/test/TestListDictionary.c
new file mode 100644
index 000000000..133271c23
--- /dev/null
+++ b/winpr/libwinpr/utils/test/TestListDictionary.c
@@ -0,0 +1,130 @@
+
+#include
+#include
+#include
+
+static char* key1 = "key1";
+static char* key2 = "key2";
+static char* key3 = "key3";
+
+static char* val1 = "val1";
+static char* val2 = "val2";
+static char* val3 = "val3";
+
+int TestListDictionary(int argc, char* argv[])
+{
+ int count;
+ char* value;
+ wListDictionary* list;
+
+ list = ListDictionary_New(FALSE);
+
+ ListDictionary_Add(list, key1, val1);
+ ListDictionary_Add(list, key2, val2);
+ ListDictionary_Add(list, key3, val3);
+
+ count = ListDictionary_Count(list);
+
+ if (count != 3)
+ {
+ printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 3, count);
+ return -1;
+ }
+
+ ListDictionary_Remove(list, key2);
+
+ count = ListDictionary_Count(list);
+
+ if (count != 2)
+ {
+ printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 2, count);
+ return -1;
+ }
+
+ ListDictionary_Remove(list, key3);
+
+ count = ListDictionary_Count(list);
+
+ if (count != 1)
+ {
+ printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 1, count);
+ return -1;
+ }
+
+ ListDictionary_Remove(list, key1);
+
+ count = ListDictionary_Count(list);
+
+ if (count != 0)
+ {
+ printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 0, count);
+ return -1;
+ }
+
+ ListDictionary_Add(list, key1, val1);
+ ListDictionary_Add(list, key2, val2);
+ ListDictionary_Add(list, key3, val3);
+
+ count = ListDictionary_Count(list);
+
+ if (count != 3)
+ {
+ printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 3, count);
+ return -1;
+ }
+
+ value = (char*) ListDictionary_GetItemValue(list, key1);
+
+ if (strcmp(value, val1) != 0)
+ {
+ printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val1, value);
+ return -1;
+ }
+
+ value = (char*) ListDictionary_GetItemValue(list, key2);
+
+ if (strcmp(value, val2) != 0)
+ {
+ printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val2, value);
+ return -1;
+ }
+
+ value = (char*) ListDictionary_GetItemValue(list, key3);
+
+ if (strcmp(value, val3) != 0)
+ {
+ printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", val3, value);
+ return -1;
+ }
+
+ ListDictionary_SetItemValue(list, key2, "apple");
+
+ value = (char*) ListDictionary_GetItemValue(list, key2);
+
+ if (strcmp(value, "apple") != 0)
+ {
+ printf("ListDictionary_GetItemValue: Expected : %d, Actual: %d\n", "apple", value);
+ return -1;
+ }
+
+ if (!ListDictionary_Contains(list, key2))
+ {
+ printf("ListDictionary_Contains: Expected : %d, Actual: %d\n", TRUE, FALSE);
+ return -1;
+ }
+
+ ListDictionary_Clear(list);
+
+ count = ListDictionary_Count(list);
+
+ if (count != 0)
+ {
+ printf("ListDictionary_Count: Expected : %d, Actual: %d\n", 0, count);
+ return -1;
+ }
+
+ ListDictionary_Free(list);
+
+ return 0;
+}
+