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 com.apple.InterfaceBuilder.CocoaPlugin 3084 - IBNSLayoutConstraint NSCustomObject - NSCustomView NSMenu NSMenuItem NSView @@ -257,24 +255,12 @@ 256 - - - - 268 - {1024, 768} - - - - _NS:9 - MRDPView - - + {1024, 768} - - + - {{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; +} +