diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index 18632b759..38e7625bd 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -312,34 +312,31 @@ static int audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallb return 0; } -static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer) +static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { int error; - wStream* s; BYTE MessageId; - s = Stream_New(pBuffer, cbSize); - - Stream_Read_UINT8(s, MessageId); + Stream_Read_UINT8(data, MessageId); DEBUG_DVC("MessageId=0x%x", MessageId); switch (MessageId) { case MSG_SNDIN_VERSION: - error = audin_process_version(pChannelCallback, s); + error = audin_process_version(pChannelCallback, data); break; case MSG_SNDIN_FORMATS: - error = audin_process_formats(pChannelCallback, s); + error = audin_process_formats(pChannelCallback, data); break; case MSG_SNDIN_OPEN: - error = audin_process_open(pChannelCallback, s); + error = audin_process_open(pChannelCallback, data); break; case MSG_SNDIN_FORMATCHANGE: - error = audin_process_format_change(pChannelCallback, s); + error = audin_process_format_change(pChannelCallback, data); break; default: @@ -348,8 +345,6 @@ static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, break; } - Stream_Free(s, FALSE); - return error; } diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index a9910cfb4..4389f5f58 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -31,7 +31,6 @@ #include #include -#include #include #include "cliprdr_main.h" diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 07b03c19c..7a7907021 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -31,7 +31,6 @@ #include #include -#include #include #include "cliprdr_main.h" @@ -382,8 +381,6 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s) DEBUG_WARN("unknown msgType %d", msgType); break; } - - Stream_Free(s, TRUE); } static void cliprdr_process_filecontents_request_event(cliprdrPlugin* plugin, RDP_CB_FILECONTENTS_REQUEST_EVENT * event) @@ -506,6 +503,7 @@ static void cliprdr_process_event(rdpSvcPlugin* plugin, wMessage* event) static void cliprdr_process_terminate(rdpSvcPlugin* plugin) { + svc_plugin_terminate(plugin); free(plugin); } diff --git a/channels/cliprdr/client/cliprdr_main.h b/channels/cliprdr/client/cliprdr_main.h index b3eabcb9d..9aec3348a 100644 --- a/channels/cliprdr/client/cliprdr_main.h +++ b/channels/cliprdr/client/cliprdr_main.h @@ -24,6 +24,7 @@ #include #include +#include struct cliprdr_plugin { diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c index 343c9e3db..e8827366b 100644 --- a/channels/disp/client/disp_main.c +++ b/channels/disp/client/disp_main.c @@ -83,11 +83,7 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback disp = (DISP_PLUGIN*) callback->plugin; -#ifdef DISP_PREVIEW - MonitorLayoutSize = 32; -#else MonitorLayoutSize = 40; -#endif length = 8 + 8 + (NumMonitors * MonitorLayoutSize); @@ -101,11 +97,7 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback 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) */ @@ -147,10 +139,8 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback 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); @@ -201,17 +191,12 @@ int disp_recv_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s) return 0; } -static int disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer) +static int disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { - 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); + status = disp_recv_pdu(callback, data); return status; } @@ -308,33 +293,34 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) disp = (DISP_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "disp"); - if (disp == NULL) + if (!disp) { - disp = (DISP_PLUGIN*) malloc(sizeof(DISP_PLUGIN)); + disp = (DISP_PLUGIN*) calloc(1, sizeof(DISP_PLUGIN)); - if (disp) - { - ZeroMemory(disp, sizeof(DISP_PLUGIN)); + if (!disp) + return -1; - disp->iface.Initialize = disp_plugin_initialize; - disp->iface.Connected = NULL; - disp->iface.Disconnected = NULL; - disp->iface.Terminated = disp_plugin_terminated; + 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 = (DispClientContext*) calloc(1, sizeof(DispClientContext)); - context->handle = (void*) disp; + if (!context) + return -1; - context->SendMonitorLayout = disp_send_monitor_layout; + context->handle = (void*) disp; - disp->iface.pInterface = (void*) context; + context->SendMonitorLayout = disp_send_monitor_layout; - disp->MaxNumMonitors = 16; - disp->MaxMonitorWidth = 8192; - disp->MaxMonitorHeight = 8192; + disp->iface.pInterface = (void*) context; - error = pEntryPoints->RegisterPlugin(pEntryPoints, "disp", (IWTSPlugin*) disp); - } + 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 index db1ce10c5..1851618a0 100644 --- a/channels/disp/client/disp_main.h +++ b/channels/disp/client/disp_main.h @@ -34,7 +34,5 @@ #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/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index d10f9a751..05146f044 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -29,45 +29,44 @@ #include #include -#include #include "dvcman.h" #include "drdynvc_types.h" #include "drdynvc_main.h" -static int drdynvc_write_variable_uint(wStream* stream, UINT32 val) +static int drdynvc_write_variable_uint(wStream* s, UINT32 val) { int cb; if (val <= 0xFF) { cb = 0; - Stream_Write_UINT8(stream, val); + Stream_Write_UINT8(s, val); } else if (val <= 0xFFFF) { cb = 1; - Stream_Write_UINT16(stream, val); + Stream_Write_UINT16(s, val); } else { cb = 2; - Stream_Write_UINT32(stream, val); + Stream_Write_UINT32(s, val); } return cb; } -int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UINT32 data_size) +int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UINT32 dataSize) { wStream* data_out; UINT32 pos = 0; UINT32 cbChId; UINT32 cbLen; - UINT32 chunk_len; - int error; + UINT32 chunkLength; + int status; - DEBUG_DVC("ChannelId=%d size=%d", ChannelId, data_size); + DEBUG_DVC("ChannelId=%d size=%d", ChannelId, dataSize); if (drdynvc->channel_error != CHANNEL_RC_OK) return 1; @@ -76,38 +75,38 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN Stream_SetPosition(data_out, 1); cbChId = drdynvc_write_variable_uint(data_out, ChannelId); - if (data_size == 0) + if (dataSize == 0) { pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x40 | cbChId); Stream_SetPosition(data_out, pos); - error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); + status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); } - else if (data_size <= CHANNEL_CHUNK_LENGTH - pos) + else if (dataSize <= CHANNEL_CHUNK_LENGTH - pos) { pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x30 | cbChId); Stream_SetPosition(data_out, pos); - Stream_Write(data_out, data, data_size); - error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); + Stream_Write(data_out, data, dataSize); + status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); } else { /* Fragment the data */ - cbLen = drdynvc_write_variable_uint(data_out, data_size); + cbLen = drdynvc_write_variable_uint(data_out, dataSize); pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); Stream_Write_UINT8(data_out, 0x20 | cbChId | (cbLen << 2)); Stream_SetPosition(data_out, pos); - chunk_len = CHANNEL_CHUNK_LENGTH - pos; - Stream_Write(data_out, data, chunk_len); - data += chunk_len; - data_size -= chunk_len; - error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); + chunkLength = CHANNEL_CHUNK_LENGTH - pos; + Stream_Write(data_out, data, chunkLength); + data += chunkLength; + dataSize -= chunkLength; + status = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); - while (error == CHANNEL_RC_OK && data_size > 0) + while (status == CHANNEL_RC_OK && dataSize > 0) { data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); Stream_SetPosition(data_out, 1); @@ -118,20 +117,20 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN Stream_Write_UINT8(data_out, 0x30 | cbChId); Stream_SetPosition(data_out, pos); - chunk_len = data_size; - if (chunk_len > CHANNEL_CHUNK_LENGTH - pos) - chunk_len = CHANNEL_CHUNK_LENGTH - pos; - Stream_Write(data_out, data, chunk_len); - data += chunk_len; - data_size -= chunk_len; - error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); + chunkLength = dataSize; + if (chunkLength > CHANNEL_CHUNK_LENGTH - pos) + chunkLength = CHANNEL_CHUNK_LENGTH - pos; + Stream_Write(data_out, data, chunkLength); + data += chunkLength; + dataSize -= chunkLength; + status = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out); } } - if (error != CHANNEL_RC_OK) + if (status != CHANNEL_RC_OK) { - drdynvc->channel_error = error; - DEBUG_WARN("VirtualChannelWrite failed %d", error); + drdynvc->channel_error = status; + DEBUG_WARN("VirtualChannelWrite failed %d", status); return 1; } @@ -140,25 +139,45 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN int drdynvc_push_event(drdynvcPlugin* drdynvc, wMessage* event) { - int error; + int status; - error = svc_plugin_send_event((rdpSvcPlugin*) drdynvc, event); + status = svc_plugin_send_event((rdpSvcPlugin*) drdynvc, event); - if (error != CHANNEL_RC_OK) + if (status != CHANNEL_RC_OK) { - DEBUG_WARN("pVirtualChannelEventPush failed %d", error); + DEBUG_WARN("pVirtualChannelEventPush failed %d", status); return 1; } return 0; } +static int drdynvc_send_capability_response(drdynvcPlugin* drdynvc) +{ + int status; + wStream* s; + + s = Stream_New(NULL, 4); + Stream_Write_UINT16(s, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */ + Stream_Write_UINT16(s, drdynvc->version); + + status = svc_plugin_send((rdpSvcPlugin*) drdynvc, s); + + if (status != CHANNEL_RC_OK) + { + DEBUG_WARN("VirtualChannelWrite failed %d", status); + return 1; + } + + return status; +} + static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { - wStream* data_out; - int error; + int status; DEBUG_DVC("Sp=%d cbChId=%d", Sp, cbChId); + Stream_Seek(s, 1); /* pad */ Stream_Read_UINT16(s, drdynvc->version); @@ -173,38 +192,31 @@ static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, in Stream_Read_UINT16(s, drdynvc->PriorityCharge3); } - data_out = Stream_New(NULL, 4); - Stream_Write_UINT16(data_out, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */ - Stream_Write_UINT16(data_out, drdynvc->version); - error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out); + status = drdynvc_send_capability_response(drdynvc); - if (error != CHANNEL_RC_OK) - { - DEBUG_WARN("VirtualChannelWrite failed %d", error); - return 1; - } + drdynvc->channel_error = status; - drdynvc->channel_error = error; + drdynvc->state = DRDYNVC_STATE_READY; return 0; } -static UINT32 drdynvc_read_variable_uint(wStream* stream, int cbLen) +static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen) { UINT32 val; switch (cbLen) { case 0: - Stream_Read_UINT8(stream, val); + Stream_Read_UINT8(s, val); break; case 1: - Stream_Read_UINT16(stream, val); + Stream_Read_UINT16(s, val); break; default: - Stream_Read_UINT32(stream, val); + Stream_Read_UINT32(s, val); break; } @@ -217,19 +229,33 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb int status; UINT32 ChannelId; wStream* data_out; + int channel_status; + + if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES) + { + /** + * For some reason the server does not always send the + * capabilities pdu as it should. When this happens, + * send a capabilities response. + */ + + drdynvc->version = 3; + drdynvc_send_capability_response(drdynvc); + drdynvc->state = DRDYNVC_STATE_READY; + } ChannelId = drdynvc_read_variable_uint(s, cbChId); pos = Stream_GetPosition(s); DEBUG_DVC("ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s)); - status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s)); + channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s)); data_out = Stream_New(NULL, pos + 4); Stream_Write_UINT8(data_out, 0x10 | cbChId); Stream_SetPosition(s, 1); Stream_Copy(data_out, s, pos - 1); - if (status == 0) + if (channel_status == 0) { DEBUG_DVC("channel created"); Stream_Write_UINT32(data_out, 0); @@ -248,6 +274,11 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb return 1; } + if (channel_status == 0) + { + dvcman_open_channel(drdynvc->channel_mgr, ChannelId); + } + return 0; } @@ -266,8 +297,7 @@ static int drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, int cbChId if (status) return status; - return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, - Stream_Pointer(s), Stream_GetRemainingLength(s)); + return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s); } static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) @@ -277,8 +307,7 @@ static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStr ChannelId = drdynvc_read_variable_uint(s, cbChId); DEBUG_DVC("ChannelId=%d", ChannelId); - return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, - Stream_Pointer(s), Stream_GetRemainingLength(s)); + return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s); } static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) @@ -350,8 +379,6 @@ static void drdynvc_process_receive(rdpSvcPlugin* plugin, wStream* s) DEBUG_WARN("unknown drdynvc cmd 0x%x", Cmd); break; } - - Stream_Free(s, TRUE); } static void drdynvc_process_connect(rdpSvcPlugin* plugin) @@ -375,6 +402,8 @@ static void drdynvc_process_connect(rdpSvcPlugin* plugin) } dvcman_init(drdynvc->channel_mgr); + + drdynvc->state = DRDYNVC_STATE_CAPABILITIES; } static void drdynvc_process_event(rdpSvcPlugin* plugin, wMessage* event) @@ -388,8 +417,16 @@ static void drdynvc_process_terminate(rdpSvcPlugin* plugin) DEBUG_DVC("terminating"); + if (!drdynvc) + return; + if (drdynvc->channel_mgr) + { dvcman_free(drdynvc->channel_mgr); + drdynvc->channel_mgr = NULL; + } + + svc_plugin_terminate(plugin); free(drdynvc); } @@ -413,8 +450,10 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) DrdynvcClientContext* context; CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; - _p = (drdynvcPlugin*) malloc(sizeof(drdynvcPlugin)); - ZeroMemory(_p, sizeof(drdynvcPlugin)); + _p = (drdynvcPlugin*) calloc(1, sizeof(drdynvcPlugin)); + + if (!_p) + return FALSE; _p->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED | @@ -423,6 +462,8 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) strcpy(_p->plugin.channel_def.name, "drdynvc"); + _p->state = DRDYNVC_STATE_INITIAL; + _p->plugin.connect_callback = drdynvc_process_connect; _p->plugin.receive_callback = drdynvc_process_receive; _p->plugin.event_callback = drdynvc_process_event; @@ -433,7 +474,10 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP)) && (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { - context = (DrdynvcClientContext*) malloc(sizeof(DrdynvcClientContext)); + context = (DrdynvcClientContext*) calloc(1, sizeof(DrdynvcClientContext)); + + if (!context) + return -1; context->handle = (void*) _p; _p->context = context; @@ -447,3 +491,4 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) return 1; } + diff --git a/channels/drdynvc/client/drdynvc_main.h b/channels/drdynvc/client/drdynvc_main.h index 369084a19..4eda9d8f5 100644 --- a/channels/drdynvc/client/drdynvc_main.h +++ b/channels/drdynvc/client/drdynvc_main.h @@ -26,6 +26,17 @@ #include #include +enum _DRDYNVC_STATE +{ + DRDYNVC_STATE_INITIAL, + DRDYNVC_STATE_CAPABILITIES, + DRDYNVC_STATE_READY, + DRDYNVC_STATE_OPENING_CHANNEL, + DRDYNVC_STATE_SEND_RECEIVE, + DRDYNVC_STATE_FINAL +}; +typedef enum _DRDYNVC_STATE DRDYNVC_STATE; + #define CREATE_REQUEST_PDU 0x01 #define DATA_FIRST_PDU 0x02 #define DATA_PDU 0x03 @@ -38,6 +49,7 @@ struct drdynvc_plugin { rdpSvcPlugin plugin; + DRDYNVC_STATE state; DrdynvcClientContext* context; int version; diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c index 670d84ecc..bd3718a60 100644 --- a/channels/drdynvc/client/dvcman.c +++ b/channels/drdynvc/client/dvcman.c @@ -3,8 +3,6 @@ * Dynamic Virtual Channel Manager * * Copyright 2010-2011 Vic Lee - * Copyright 2014 Thincast Technologies GmbH - * Copyright 2014 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,9 +21,6 @@ #include "config.h" #endif -#include -#include - #include #include #include @@ -33,61 +28,45 @@ #include #include #include -#include #include #include "drdynvc_types.h" #include "dvcman.h" -static wListDictionary *cb_dict = NULL; -struct cb_value -{ - void *fkt; - void *context; -}; -static int dvcman_get_configuration(IWTSListener *pListener, void **ppPropertyBag) +static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag) { - if (!ppPropertyBag) - { - DEBUG_WARN("ppPropertyBag=%p", ppPropertyBag); - return 0; - } - *ppPropertyBag = NULL; return 1; } -static int dvcman_create_listener(IWTSVirtualChannelManager *pChannelMgr, - const char *pszChannelName, UINT32 ulFlags, - IWTSListenerCallback *pListenerCallback, IWTSListener **ppListener) +static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr, + const char* pszChannelName, UINT32 ulFlags, + IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener) { - DVCMAN *dvcman = (DVCMAN *) pChannelMgr; - DVCMAN_LISTENER *listener; - assert(dvcman); + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; + DVCMAN_LISTENER* listener; if (dvcman->num_listeners < MAX_PLUGINS) { DEBUG_DVC("%d.%s.", dvcman->num_listeners, pszChannelName); - listener = (DVCMAN_LISTENER *) calloc(1, sizeof(DVCMAN_LISTENER)); - if (!listener) - { - DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno); - return 2; - } + listener = (DVCMAN_LISTENER*) malloc(sizeof(DVCMAN_LISTENER)); + ZeroMemory(listener, sizeof(DVCMAN_LISTENER)); listener->iface.GetConfiguration = dvcman_get_configuration; listener->iface.pInterface = NULL; + listener->dvcman = dvcman; listener->channel_name = _strdup(pszChannelName); listener->flags = ulFlags; listener->listener_callback = pListenerCallback; if (ppListener) - *ppListener = (IWTSListener *) listener; + *ppListener = (IWTSListener*) listener; - dvcman->listeners[dvcman->num_listeners++] = (IWTSListener *) listener; + dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*) listener; + return 0; } else @@ -97,11 +76,11 @@ static int dvcman_create_listener(IWTSVirtualChannelManager *pChannelMgr, } } -static int dvcman_push_event(IWTSVirtualChannelManager *pChannelMgr, wMessage *pEvent) +static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr, wMessage* pEvent) { int status; - DVCMAN *dvcman = (DVCMAN *) pChannelMgr; - assert(dvcman); + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; + status = drdynvc_push_event(dvcman->drdynvc, pEvent); if (status == 0) @@ -116,11 +95,9 @@ static int dvcman_push_event(IWTSVirtualChannelManager *pChannelMgr, wMessage *p return status; } -static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const char *name, IWTSPlugin *pPlugin) +static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name, IWTSPlugin* pPlugin) { - DVCMAN *dvcman = ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->dvcman; - assert(pEntryPoints); - assert(dvcman); + DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman; if (dvcman->num_plugins < MAX_PLUGINS) { @@ -136,17 +113,15 @@ static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const cha } } -IWTSPlugin *dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const char *name) +IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name) { int i; - DVCMAN *dvcman = ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->dvcman; - assert(pEntryPoints); - assert(dvcman); + DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman; for (i = 0; i < dvcman->num_plugins; i++) { if (dvcman->plugin_names[i] == name || - strcmp(dvcman->plugin_names[i], name) == 0) + strcmp(dvcman->plugin_names[i], name) == 0) { return dvcman->plugins[i]; } @@ -155,28 +130,27 @@ IWTSPlugin *dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS *pEntryPoints, const char *n return NULL; } -ADDIN_ARGV *dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS *pEntryPoints) +ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - assert(pEntryPoints); - return ((DVCMAN_ENTRY_POINTS *) pEntryPoints)->args; + return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->args; } -UINT32 dvcman_get_channel_id(IWTSVirtualChannel *channel) +UINT32 dvcman_get_channel_id(IWTSVirtualChannel * channel) { - assert(channel); - return ((DVCMAN_CHANNEL *) channel)->channel_id; + return ((DVCMAN_CHANNEL*) channel)->channel_id; } -IWTSVirtualChannel *dvcman_find_channel_by_id(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId) +IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId) { int index; BOOL found = FALSE; - DVCMAN_CHANNEL *channel; - DVCMAN *dvcman = (DVCMAN *) pChannelMgr; - assert(dvcman); + DVCMAN_CHANNEL* channel; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; + ArrayList_Lock(dvcman->channels); + index = 0; - channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, index++); + channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++); while (channel) { @@ -186,26 +160,25 @@ IWTSVirtualChannel *dvcman_find_channel_by_id(IWTSVirtualChannelManager *pChanne break; } - channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, index++); + channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++); } ArrayList_Unlock(dvcman->channels); - return (found) ? ((IWTSVirtualChannel *) channel) : NULL; + + return (found) ? ((IWTSVirtualChannel*) channel) : NULL; } -void *dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager *pChannelMgr, const char *ChannelName) +void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName) { int i; BOOL found = FALSE; - void *pInterface = NULL; - DVCMAN_LISTENER *listener; - DVCMAN *dvcman = (DVCMAN *) pChannelMgr; - assert(dvcman); + void* pInterface = NULL; + DVCMAN_LISTENER* listener; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; for (i = 0; i < dvcman->num_listeners; i++) { - listener = (DVCMAN_LISTENER *) dvcman->listeners[i]; - assert(listener); + listener = (DVCMAN_LISTENER*) dvcman->listeners[i]; if (strcmp(listener->channel_name, ChannelName) == 0) { @@ -218,16 +191,11 @@ void *dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager *pChannelMg return (found) ? pInterface : NULL; } -IWTSVirtualChannelManager *dvcman_new(drdynvcPlugin *plugin) +IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) { - DVCMAN *dvcman; - dvcman = (DVCMAN *) calloc(1,sizeof(DVCMAN)); + DVCMAN* dvcman; - if (!dvcman) - { - DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno); - return NULL; - } + dvcman = (DVCMAN*) calloc(1, sizeof(DVCMAN)); dvcman->iface.CreateListener = dvcman_create_listener; dvcman->iface.PushEvent = dvcman_push_event; @@ -235,68 +203,71 @@ IWTSVirtualChannelManager *dvcman_new(drdynvcPlugin *plugin) dvcman->iface.GetChannelId = dvcman_get_channel_id; dvcman->drdynvc = plugin; dvcman->channels = ArrayList_New(TRUE); - return (IWTSVirtualChannelManager *) dvcman; + dvcman->pool = StreamPool_New(TRUE, 10); + + return (IWTSVirtualChannelManager*) dvcman; } -int dvcman_load_addin(IWTSVirtualChannelManager *pChannelMgr, ADDIN_ARGV *args) +int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args) { DVCMAN_ENTRY_POINTS entryPoints; PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL; - assert(args); + fprintf(stderr, "Loading Dynamic Virtual Channel %s\n", args->argv[0]); + pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry(args->argv[0], - NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC); + NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC); if (pDVCPluginEntry) { entryPoints.iface.RegisterPlugin = dvcman_register_plugin; entryPoints.iface.GetPlugin = dvcman_get_plugin; entryPoints.iface.GetPluginData = dvcman_get_plugin_data; - entryPoints.dvcman = (DVCMAN *) pChannelMgr; + entryPoints.dvcman = (DVCMAN*) pChannelMgr; entryPoints.args = args; - pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS *) &entryPoints); + + pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints); } return 0; } -static void dvcman_channel_free(DVCMAN_CHANNEL *channel) +static void dvcman_channel_free(DVCMAN_CHANNEL* channel) { - assert(channel); - if (channel->channel_callback) channel->channel_callback->OnClose(channel->channel_callback); - if (channel->channel_name) - free(channel->channel_name); + DeleteCriticalSection(&(channel->lock)); free(channel); } -void dvcman_free(IWTSVirtualChannelManager *pChannelMgr) +void dvcman_free(IWTSVirtualChannelManager* pChannelMgr) { int i; int count; - IWTSPlugin *pPlugin; - DVCMAN_LISTENER *listener; - DVCMAN_CHANNEL *channel; - DVCMAN *dvcman = (DVCMAN *) pChannelMgr; - assert(dvcman); + IWTSPlugin* pPlugin; + DVCMAN_LISTENER* listener; + DVCMAN_CHANNEL* channel; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; + ArrayList_Lock(dvcman->channels); + count = ArrayList_Count(dvcman->channels); for (i = 0; i < count; i++) { - channel = (DVCMAN_CHANNEL *) ArrayList_GetItem(dvcman->channels, i); + channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, i); dvcman_channel_free(channel); } ArrayList_Unlock(dvcman->channels); + ArrayList_Free(dvcman->channels); for (i = 0; i < dvcman->num_listeners; i++) { - listener = (DVCMAN_LISTENER *) dvcman->listeners[i]; + listener = (DVCMAN_LISTENER*) dvcman->listeners[i]; free(listener->channel_name); free(listener); } @@ -309,15 +280,15 @@ void dvcman_free(IWTSVirtualChannelManager *pChannelMgr) pPlugin->Terminated(pPlugin); } + StreamPool_Free(dvcman->pool); free(dvcman); } -int dvcman_init(IWTSVirtualChannelManager *pChannelMgr) +int dvcman_init(IWTSVirtualChannelManager* pChannelMgr) { int i; - IWTSPlugin *pPlugin; - DVCMAN *dvcman = (DVCMAN *) pChannelMgr; - assert(dvcman); + IWTSPlugin* pPlugin; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; for (i = 0; i < dvcman->num_plugins; i++) { @@ -330,83 +301,88 @@ int dvcman_init(IWTSVirtualChannelManager *pChannelMgr) return 0; } -static int dvcman_write_channel(IWTSVirtualChannel *pChannel, UINT32 cbSize, BYTE *pBuffer, void *pReserved) +static int dvcman_write_channel(IWTSVirtualChannel* pChannel, UINT32 cbSize, BYTE* pBuffer, void* pReserved) { int status; - DVCMAN_CHANNEL *channel = (DVCMAN_CHANNEL *) pChannel; - assert(channel); - WaitForSingleObject(channel->dvc_chan_mutex, INFINITE); + DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel; + + EnterCriticalSection(&(channel->lock)); + status = drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize); - ReleaseMutex(channel->dvc_chan_mutex); + + LeaveCriticalSection(&(channel->lock)); + return status; } -static int dvcman_close_channel_iface(IWTSVirtualChannel *pChannel) +static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel) { - DVCMAN_CHANNEL *channel = (DVCMAN_CHANNEL *) pChannel; - DVCMAN *dvcman = channel->dvcman; - assert(channel); - assert(dvcman); + DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel; + DVCMAN* dvcman = channel->dvcman; + DEBUG_DVC("id=%d", channel->channel_id); + ArrayList_Remove(dvcman->channels, channel); + dvcman_channel_free(channel); + return 1; } -int dvcman_create_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, const char *ChannelName) +int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName) { int i; int bAccept; - DVCMAN_LISTENER *listener; - DVCMAN_CHANNEL *channel; - DrdynvcClientContext *context; - IWTSVirtualChannelCallback *pCallback; - DVCMAN *dvcman = (DVCMAN *) pChannelMgr; - channel = (DVCMAN_CHANNEL *) calloc(1, sizeof(DVCMAN_CHANNEL)); + DVCMAN_LISTENER* listener; + DVCMAN_CHANNEL* channel; + DrdynvcClientContext* context; + IWTSVirtualChannelCallback* pCallback; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; + + channel = (DVCMAN_CHANNEL*) calloc(1, sizeof(DVCMAN_CHANNEL)); if (!channel) - { - DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno); return -1; - } - ZeroMemory(channel, sizeof(DVCMAN_CHANNEL)); channel->dvcman = dvcman; channel->channel_id = ChannelId; channel->channel_name = _strdup(ChannelName); for (i = 0; i < dvcman->num_listeners; i++) { - listener = (DVCMAN_LISTENER *) dvcman->listeners[i]; - assert(listener); + listener = (DVCMAN_LISTENER*) dvcman->listeners[i]; if (strcmp(listener->channel_name, ChannelName) == 0) { channel->iface.Write = dvcman_write_channel; channel->iface.Close = dvcman_close_channel_iface; - channel->dvc_chan_mutex = CreateMutex(NULL, FALSE, NULL); + + InitializeCriticalSection(&(channel->lock)); + bAccept = 1; pCallback = NULL; - assert(listener->listener_callback); - assert(listener->listener_callback->OnNewChannelConnection); if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback, - (IWTSVirtualChannel *) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1) + (IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1) { DEBUG_DVC("listener %s created new channel %d", - listener->channel_name, channel->channel_id); + listener->channel_name, channel->channel_id); + channel->status = 0; channel->channel_callback = pCallback; channel->pInterface = listener->iface.pInterface; - assert(dvcman->drdynvc); + ArrayList_Add(dvcman->channels, channel); + context = dvcman->drdynvc->context; IFCALL(context->OnChannelConnected, context, ChannelName, listener->iface.pInterface); + return 0; } else { DEBUG_WARN("channel rejected by plugin"); + free(channel); return 1; } @@ -417,14 +393,36 @@ int dvcman_create_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 Channel return 1; } -int dvcman_close_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId) +int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId) { - DVCMAN_CHANNEL *channel; - IWTSVirtualChannel *ichannel; - DrdynvcClientContext *context; - DVCMAN *dvcman = (DVCMAN *) pChannelMgr; - assert(dvcman); - channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId); + DVCMAN_CHANNEL* channel; + IWTSVirtualChannelCallback* pCallback; + + channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); + + if (!channel) + { + DEBUG_WARN("ChannelId %d not found!", ChannelId); + return 1; + } + + if (channel->status == 0) + { + pCallback = channel->channel_callback; + pCallback->OnOpen(pCallback); + } + + return 0; +} + +int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId) +{ + DVCMAN_CHANNEL* channel; + IWTSVirtualChannel* ichannel; + DrdynvcClientContext* context; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; + + channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { @@ -434,27 +432,31 @@ int dvcman_close_channel(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelI if (channel->dvc_data) { - Stream_Free(channel->dvc_data, TRUE); + Stream_Release(channel->dvc_data); channel->dvc_data = NULL; } if (channel->status == 0) { - assert(dvcman->drdynvc); context = dvcman->drdynvc->context; + IFCALL(context->OnChannelDisconnected, context, channel->channel_name, channel->pInterface); + + free(channel->channel_name); + DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId); - ichannel = (IWTSVirtualChannel *) channel; + ichannel = (IWTSVirtualChannel*) channel; ichannel->Close(ichannel); } return 0; } -int dvcman_receive_channel_data_first(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, UINT32 length) +int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length) { - DVCMAN_CHANNEL *channel; - channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId); + DVCMAN_CHANNEL* channel; + + channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { @@ -463,17 +465,21 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager *pChannelMgr, UI } if (channel->dvc_data) - Stream_Free(channel->dvc_data, TRUE); + Stream_Release(channel->dvc_data); + + channel->dvc_data = StreamPool_Take(channel->dvcman->pool, length); + Stream_AddRef(channel->dvc_data); - channel->dvc_data = Stream_New(NULL, length); return 0; } -int dvcman_receive_channel_data(IWTSVirtualChannelManager *pChannelMgr, UINT32 ChannelId, BYTE *data, UINT32 data_size) +int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data) { - int error = 0; - DVCMAN_CHANNEL *channel; - channel = (DVCMAN_CHANNEL *) dvcman_find_channel_by_id(pChannelMgr, ChannelId); + int status = 0; + DVCMAN_CHANNEL* channel; + UINT32 dataSize = Stream_GetRemainingLength(data); + + channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { @@ -484,135 +490,30 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager *pChannelMgr, UINT32 C if (channel->dvc_data) { /* Fragmented data */ - if (Stream_GetPosition(channel->dvc_data) + data_size > (UINT32) Stream_Capacity(channel->dvc_data)) + if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(channel->dvc_data)) { DEBUG_WARN("data exceeding declared length!"); - Stream_Free(channel->dvc_data, TRUE); + Stream_Release(channel->dvc_data); channel->dvc_data = NULL; return 1; } - Stream_Write(channel->dvc_data, data, data_size); + Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize); if (((size_t) Stream_GetPosition(channel->dvc_data)) >= Stream_Capacity(channel->dvc_data)) { - error = channel->channel_callback->OnDataReceived(channel->channel_callback, - Stream_Capacity(channel->dvc_data), Stream_Buffer(channel->dvc_data)); - Stream_Free(channel->dvc_data, TRUE); + Stream_SealLength(channel->dvc_data); + Stream_SetPosition(channel->dvc_data, 0); + status = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data); + Stream_Release(channel->dvc_data); channel->dvc_data = NULL; } } else { - assert(channel->channel_callback); - assert(channel->channel_callback->OnDataReceived); - error = channel->channel_callback->OnDataReceived(channel->channel_callback, data_size, data); + status = channel->channel_callback->OnDataReceived(channel->channel_callback, data); } - return error; + return status; } -static void dump_callbacks(void) -{ - wListDictionaryItem *cur; - DEBUG_DVC("Dumping all currently registered callbacks"); - - if (!cb_dict) - { - DEBUG_DVC("cb_dict=NULL"); - return; - } - - cur = cb_dict->head; - - while (cur) - { - DEBUG_DVC("cb_dict %s:%p", cur->key, cur->value); - cur = cur->next; - } -} - -void *get_callback_by_name(const char *name, void **context) -{ - struct cb_value *rc; - - if (!cb_dict) - { - DEBUG_WARN("'%s' not found, function list does not exist.", - name); - return NULL; - } - - if (!ListDictionary_Contains(cb_dict, (void *)name)) - { - DEBUG_WARN("'%s' not found", name); - return NULL; - } - - rc = ListDictionary_GetItemValue(cb_dict, (void *)name); - DEBUG_DVC("'%s'=%p found", name, rc); - - if (context) - *context = rc->context; - - return rc->fkt; -} - -static BOOL callback_key_cmp(void *a, void *b) -{ - return strcmp(a, b) ? FALSE : TRUE; -} - -void add_callback_by_name(const char *name, void *fkt, void *context) -{ - struct cb_value *value = calloc(1, sizeof(struct cb_value)); - - if (!value) - { - DEBUG_WARN("calloc failed %s (%d)!", strerror(errno), errno); - assert(FALSE); - return; - } - - if (!cb_dict) - { - DEBUG_DVC("Function list is empty, allocating new."); - cb_dict = ListDictionary_New(TRUE); - ListDictionary_KeyObject(cb_dict)->fnObjectEquals = callback_key_cmp; - } - - value->fkt = fkt; - value->context = context; - DEBUG_DVC("Adding '%s'=%p to function list.", name, fkt); - ListDictionary_Add(cb_dict, (void *)name, value); - dump_callbacks(); -} - -void remove_callback_by_name(const char *name, void *context) -{ - if (!cb_dict) - { - DEBUG_WARN("trying to remove '%s', but function list does not exist.", - name); - return; - } - - if (!ListDictionary_Contains(cb_dict, (void *)name)) - { - DEBUG_WARN("trying to remove '%s', which is not in function list.", - name); - return; - } - - DEBUG_DVC("Removing '%s' from function list.", name); - ListDictionary_Remove(cb_dict, (void *)name); - - if (ListDictionary_Count(cb_dict) < 1) - { - DEBUG_DVC("Function list is empty, freeing resources."); - ListDictionary_Free(cb_dict); - cb_dict = NULL; - } - - dump_callbacks(); -} diff --git a/channels/drdynvc/client/dvcman.h b/channels/drdynvc/client/dvcman.h index ca886f3af..3b627eae4 100644 --- a/channels/drdynvc/client/dvcman.h +++ b/channels/drdynvc/client/dvcman.h @@ -23,6 +23,7 @@ #include #include +#include #include #include "drdynvc_main.h" @@ -43,6 +44,7 @@ struct _DVCMAN int num_listeners; wArrayList* channels; + wStreamPool* pool; }; typedef struct _DVCMAN DVCMAN; @@ -78,7 +80,7 @@ struct _DVCMAN_CHANNEL IWTSVirtualChannelCallback* channel_callback; wStream* dvc_data; - HANDLE dvc_chan_mutex; + CRITICAL_SECTION lock; }; typedef struct _DVCMAN_CHANNEL DVCMAN_CHANNEL; @@ -87,9 +89,10 @@ int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args); void dvcman_free(IWTSVirtualChannelManager* pChannelMgr); int dvcman_init(IWTSVirtualChannelManager* pChannelMgr); int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName); +int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId); int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId); int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length); -int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, BYTE* data, UINT32 data_size); +int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream *data); void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName); diff --git a/channels/echo/client/echo_main.c b/channels/echo/client/echo_main.c index 595844918..ef381e21a 100644 --- a/channels/echo/client/echo_main.c +++ b/channels/echo/client/echo_main.c @@ -61,10 +61,12 @@ struct _ECHO_PLUGIN ECHO_LISTENER_CALLBACK* listener_callback; }; -static int echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer) +static int echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { int error; ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*) pChannelCallback; + BYTE *pBuffer = Stream_Pointer(data); + UINT32 cbSize = Stream_GetRemainingLength(data); #ifdef WITH_DEBUG_DVC int i = 0; diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c index ff6da340a..a6b5d8985 100644 --- a/channels/parallel/client/parallel_main.c +++ b/channels/parallel/client/parallel_main.c @@ -47,13 +47,12 @@ #include #include #include +#include #include #include #include #include -#include -#include #include struct _PARALLEL_DEVICE @@ -93,16 +92,14 @@ static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp) { irp->IoStatus = STATUS_ACCESS_DENIED; parallel->id = 0; - - DEBUG_WARN("failed to create %s: %s", parallel->path, strerror(errno)); } else { /* all read and write operations should be non-blocking */ if (fcntl(parallel->file, F_SETFL, O_NONBLOCK) == -1) - DEBUG_WARN("%s fcntl %s", path, strerror(errno)); + { - DEBUG_SVC("%s(%d) created", parallel->path, parallel->file); + } } Stream_Write_UINT32(irp->output, parallel->id); @@ -116,9 +113,13 @@ static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp) static void parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp) { if (close(parallel->file) < 0) - DEBUG_SVC("failed to close %s(%d)", parallel->path, parallel->id); + { + + } else - DEBUG_SVC("%s(%d) closed", parallel->path, parallel->id); + { + + } Stream_Zero(irp->output, 5); /* Padding(5) */ @@ -145,12 +146,10 @@ static void parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp) free(buffer); buffer = NULL; Length = 0; - - DEBUG_WARN("read %s(%d) failed", parallel->path, parallel->id); } else { - DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, parallel->id); + } Stream_Write_UINT32(irp->output, Length); @@ -177,8 +176,6 @@ static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) Stream_Read_UINT64(irp->input, Offset); Stream_Seek(irp->input, 20); /* Padding */ - DEBUG_SVC("Length %u Offset %llu", Length, Offset); - len = Length; while (len > 0) @@ -189,8 +186,6 @@ static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; - - DEBUG_WARN("write %s(%d) failed.", parallel->path, parallel->id); break; } @@ -206,15 +201,12 @@ static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) static void parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP* irp) { - DEBUG_SVC("in"); Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */ irp->Complete(irp); } static void parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) { - DEBUG_SVC("MajorFunction %u", irp->MajorFunction); - switch (irp->MajorFunction) { case IRP_MJ_CREATE: @@ -238,7 +230,6 @@ static void parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) break; default: - DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; @@ -281,8 +272,6 @@ static void parallel_free(DEVICE* device) { PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; - DEBUG_SVC("freeing device"); - MessageQueue_PostQuit(parallel->queue, 0); WaitForSingleObject(parallel->thread, INFINITE); CloseHandle(parallel->thread); diff --git a/channels/printer/client/printer_cups.c b/channels/printer/client/printer_cups.c index aa9b0ee2b..0d6fcbeb9 100644 --- a/channels/printer/client/printer_cups.c +++ b/channels/printer/client/printer_cups.c @@ -31,7 +31,6 @@ #include -#include #include #include "printer_main.h" @@ -87,15 +86,12 @@ static void printer_cups_write_printjob(rdpPrintJob* printjob, BYTE* data, int s fp = fopen((const char*) cups_printjob->printjob_object, "a+b"); - if (fp == NULL) - { - DEBUG_WARN("failed to open file %s", (char*) cups_printjob->printjob_object); + if (!fp) return; - } if (fwrite(data, 1, size, fp) < size) { - DEBUG_WARN("failed to write file %s", (char*) cups_printjob->printjob_object); + } fclose(fp); @@ -121,7 +117,7 @@ static void printer_cups_close_printjob(rdpPrintJob* printjob) if (cupsPrintFile(printjob->printer->name, (const char*) cups_printjob->printjob_object, buf, 0, NULL) == 0) { - DEBUG_WARN("cupsPrintFile: %s", cupsLastErrorString()); + } unlink(cups_printjob->printjob_object); @@ -167,20 +163,19 @@ static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id) cups_printjob->printjob_object = httpConnectEncrypt(cupsServer(), ippPort(), HTTP_ENCRYPT_IF_REQUESTED); - if (cups_printjob->printjob_object == NULL) + if (!cups_printjob->printjob_object) { - DEBUG_WARN("httpConnectEncrypt: %s", cupsLastErrorString()); free(cups_printjob); return NULL; } printer_cups_get_printjob_name(buf, sizeof(buf)); + cups_printjob->printjob_id = cupsCreateJob((http_t*) cups_printjob->printjob_object, printer->name, buf, 0, NULL); - if (cups_printjob->printjob_id == 0) + if (!cups_printjob->printjob_id) { - DEBUG_WARN("cupsCreateJob: %s", cupsLastErrorString()); httpClose((http_t*) cups_printjob->printjob_object); free(cups_printjob); return NULL; @@ -281,19 +276,15 @@ rdpPrinterDriver* printer_cups_get_driver(void) { if (cups_driver == NULL) { - cups_driver = (rdpCupsPrinterDriver*) malloc(sizeof(rdpCupsPrinterDriver)); - ZeroMemory(cups_driver, sizeof(rdpCupsPrinterDriver)); + cups_driver = (rdpCupsPrinterDriver*) calloc(1, sizeof(rdpCupsPrinterDriver)); + + if (!cups_driver) + return NULL; cups_driver->driver.EnumPrinters = printer_cups_enum_printers; cups_driver->driver.GetPrinter = printer_cups_get_printer; cups_driver->id_sequence = 1; - -#ifdef _CUPS_API_1_4 - DEBUG_SVC("using CUPS API 1.4"); -#else - DEBUG_SVC("using CUPS API 1.2"); -#endif } return (rdpPrinterDriver*) cups_driver; diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index b3b17fb04..40ba570ce 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -28,11 +28,10 @@ #include #include #include +#include #include -#include #include -#include #ifdef WITH_CUPS #include "printer_cups.h" @@ -69,15 +68,11 @@ static void printer_process_irp_create(PRINTER_DEVICE* printer_dev, IRP* irp) if (printjob) { Stream_Write_UINT32(irp->output, printjob->id); /* FileId */ - - DEBUG_SVC("printjob id: %d", printjob->id); } else { Stream_Write_UINT32(irp->output, 0); /* FileId */ irp->IoStatus = STATUS_PRINT_QUEUE_FULL; - - DEBUG_WARN("error creating print job."); } irp->Complete(irp); @@ -87,20 +82,16 @@ static void printer_process_irp_close(PRINTER_DEVICE* printer_dev, IRP* irp) { rdpPrintJob* printjob = NULL; - if (printer_dev->printer != NULL) + if (printer_dev->printer) printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId); if (!printjob) { irp->IoStatus = STATUS_UNSUCCESSFUL; - - DEBUG_WARN("printjob id %d not found.", irp->FileId); } else { printjob->Close(printjob); - - DEBUG_SVC("printjob id %d closed.", irp->FileId); } Stream_Zero(irp->output, 4); /* Padding(4) */ @@ -125,14 +116,10 @@ static void printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; - - DEBUG_WARN("printjob id %d not found.", irp->FileId); } else { printjob->Write(printjob, Stream_Pointer(irp->input), Length); - - DEBUG_SVC("printjob id %d written %d bytes.", irp->FileId, Length); } Stream_Write_UINT32(irp->output, Length); @@ -168,7 +155,6 @@ static void printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp) break; default: - DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; @@ -267,8 +253,6 @@ void printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri CachedFieldsLen = 0; CachedPrinterConfigData = NULL; - DEBUG_SVC("Printer %s registered", printer->name); - Flags = 0; if (printer->is_default) @@ -332,9 +316,8 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) driver = printer_win_get_driver(); #endif - if (driver == NULL) + if (!driver) { - DEBUG_WARN("no driver"); return 1; } @@ -347,10 +330,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) printer = driver->GetPrinter(driver, name); if (!printer) - { - DEBUG_WARN("printer %s not found.", name); return 1; - } if (driver_name && driver_name[0]) printer->driver = driver_name; diff --git a/channels/printer/client/printer_win.c b/channels/printer/client/printer_win.c index 733b24ff0..fcbbbc1fd 100644 --- a/channels/printer/client/printer_win.c +++ b/channels/printer/client/printer_win.c @@ -30,8 +30,6 @@ #include #include -#include - #include "printer_main.h" #include "printer_win.h" @@ -69,45 +67,44 @@ static void printer_win_get_printjob_name(char* buf, int size) time_t tt; struct tm* t; - DEBUG_WINPR(""); - tt = time(NULL); t = localtime(&tt); snprintf(buf, size - 1, "FreeRDP Print Job %d%02d%02d%02d%02d%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); - - DEBUG_WINPR("buf: %s", buf); - } static void printer_win_write_printjob(rdpPrintJob* printjob, BYTE* data, int size) { - rdpWinPrintJob* win_printjob = (rdpWinPrintJob*)printjob; + rdpWinPrintJob* win_printjob = (rdpWinPrintJob*) printjob; LPVOID pBuf = data; DWORD cbBuf = size; DWORD pcWritten; - if( ! WritePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter, pBuf, cbBuf, &pcWritten ) ) - DEBUG_WINPR("WritePrinter failed"); -; - + if(!WritePrinter(((rdpWinPrinter*)printjob->printer)->hPrinter, pBuf, cbBuf, &pcWritten)) + { + + } } static void printer_win_close_printjob(rdpPrintJob* printjob) { - rdpWinPrintJob* win_printjob = (rdpWinPrintJob*)printjob; + rdpWinPrintJob* win_printjob = (rdpWinPrintJob*) printjob; - DEBUG_WINPR(""); + if (!EndPagePrinter(((rdpWinPrinter*) printjob->printer)->hPrinter)) + { - if ( ! EndPagePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter ) ) - DEBUG_WINPR("EndPagePrinter failed");; - if ( ! ClosePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter ) ) - DEBUG_WINPR("ClosePrinter failed");; + } - ((rdpWinPrinter*)printjob->printer)->printjob = NULL; - free(win_printjob) ; + if (!ClosePrinter(((rdpWinPrinter*) printjob->printer)->hPrinter)) + { + + } + + ((rdpWinPrinter*) printjob->printer)->printjob = NULL; + + free(win_printjob); } static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id) @@ -115,13 +112,10 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id) rdpWinPrinter* win_printer = (rdpWinPrinter*)printer; rdpWinPrintJob* win_printjob; - DEBUG_WINPR(""); - if (win_printer->printjob != NULL) return NULL; - win_printjob = (rdpWinPrintJob*) malloc(sizeof(rdpWinPrintJob)); - ZeroMemory(win_printjob, sizeof(rdpWinPrintJob)); + win_printjob = (rdpWinPrintJob*) calloc(1, sizeof(rdpWinPrintJob)); win_printjob->printjob.id = id; win_printjob->printjob.printer = printer; @@ -132,10 +126,14 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id) win_printjob->handle = StartDocPrinter(win_printer->hPrinter, 1, (LPBYTE) &(win_printjob->di)); if (!win_printjob->handle) - DEBUG_WINPR("StartDocPrinter failed"); + { + + } if (!StartPagePrinter(win_printer->hPrinter)) - DEBUG_WINPR("ClosePrinter failed"); + { + + } win_printjob->printjob.Write = printer_win_write_printjob; win_printjob->printjob.Close = printer_win_close_printjob; @@ -149,9 +147,7 @@ static rdpPrintJob* printer_win_find_printjob(rdpPrinter* printer, UINT32 id) { rdpWinPrinter* win_printer = (rdpWinPrinter*) printer; - DEBUG_WINPR(""); - - if (win_printer->printjob == NULL) + if (!win_printer->printjob) return NULL; if (win_printer->printjob->printjob.id != id) @@ -164,8 +160,6 @@ static void printer_win_free_printer(rdpPrinter* printer) { rdpWinPrinter* win_printer = (rdpWinPrinter*) printer; - DEBUG_WINPR(""); - if (win_printer->printjob) win_printer->printjob->printjob.Close((rdpPrintJob*) win_printer->printjob); @@ -180,10 +174,8 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons DWORD needed; PRINTER_INFO_2 *prninfo=NULL; size_t charsConverted; - DEBUG_WINPR(""); - win_printer = (rdpWinPrinter*) malloc(sizeof(rdpWinPrinter)); - ZeroMemory(win_printer, sizeof(rdpWinPrinter)); + win_printer = (rdpWinPrinter*) calloc(1, sizeof(rdpWinPrinter)); win_printer->printer.id = win_driver->id_sequence++; win_printer->printer.name = _strdup(name); @@ -195,7 +187,6 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons swprintf(wname, 256, L"%hs", name); OpenPrinter(wname, &(win_printer->hPrinter), NULL); - DEBUG_WINPR("handle: 0x%08X", win_printer->hPrinter); GetPrinter(win_printer->hPrinter, 2, (LPBYTE) prninfo, 0, &needed); prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed); @@ -216,8 +207,6 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver) size_t charsConverted; PRINTER_INFO_2* prninfo = NULL; DWORD needed, returned; - - DEBUG_WINPR(""); /* find required size for the buffer */ EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &returned); @@ -227,19 +216,16 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver) prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed); /* call again */ - if ( !EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE) prninfo, needed, &needed, &returned) ) + if (!EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE) prninfo, needed, &needed, &returned)) { - DEBUG_WINPR("EnumPrinters failed"); - } ; /* ERROR... */ - DEBUG_WINPR("printers found: %d", returned); + } - printers = (rdpPrinter**) malloc(sizeof(rdpPrinter*) * (returned + 1)); - ZeroMemory(printers, sizeof(rdpPrinter*) * (returned + 1)); + printers = (rdpPrinter**) calloc((returned + 1), sizeof(rdpPrinter*)); num_printers = 0; - for (i = 0; i < (int)returned; i++) + for (i = 0; i < (int) returned; i++) { wcstombs_s(&charsConverted, pname, 1000, prninfo[i].pPrinterName, _TRUNCATE); printers[num_printers++] = printer_win_new_printer((rdpWinPrinterDriver*)driver, @@ -254,8 +240,6 @@ static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver, const char* { rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver; rdpPrinter *myPrinter = NULL; - - DEBUG_WINPR("printer %s", name); myPrinter = printer_win_new_printer(win_driver, name, L"", win_driver->id_sequence == 1 ? TRUE : FALSE); @@ -266,12 +250,9 @@ static rdpWinPrinterDriver* win_driver = NULL; rdpPrinterDriver* printer_win_get_driver(void) { - DEBUG_WINPR(""); - - if (win_driver == NULL) + if (!win_driver) { - win_driver = (rdpWinPrinterDriver*) malloc(sizeof(rdpWinPrinterDriver)); - ZeroMemory(win_driver, sizeof(rdpWinPrinterDriver)); + win_driver = (rdpWinPrinterDriver*) calloc(1, sizeof(rdpWinPrinterDriver)); win_driver->driver.EnumPrinters = printer_win_enum_printers; win_driver->driver.GetPrinter = printer_win_get_printer; diff --git a/channels/rail/client/rail_main.c b/channels/rail/client/rail_main.c index 99934bbfd..17d585716 100644 --- a/channels/rail/client/rail_main.c +++ b/channels/rail/client/rail_main.c @@ -31,7 +31,6 @@ #include #include -#include #include #include @@ -95,13 +94,13 @@ static void rail_process_terminate(rdpSvcPlugin* plugin) railPlugin* rail = (railPlugin*) plugin; WLog_Print(rail->log, WLOG_DEBUG, "Terminate"); + svc_plugin_terminate(plugin); } static void rail_process_receive(rdpSvcPlugin* plugin, wStream* s) { railPlugin* rail = (railPlugin*) plugin; rail_order_recv(rail, s); - Stream_Free(s, TRUE); } static void rail_process_addin_args(rdpRailOrder* railOrder, rdpSettings* settings) @@ -507,8 +506,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) RailClientContext* context; CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; - rail = (railPlugin*) malloc(sizeof(railPlugin)); - ZeroMemory(rail, sizeof(railPlugin)); + rail = (railPlugin*) calloc(1, sizeof(railPlugin)); rail->plugin.channel_def.options = CHANNEL_OPTION_INITIALIZED | diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index 9eff40876..cd837669f 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -434,17 +434,12 @@ int rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) return 0; } -static int rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer) +static int rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { - wStream* s; int status = 0; RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback; - s = Stream_New(pBuffer, cbSize); - - status = rdpei_recv_pdu(callback, s); - - Stream_Free(s, FALSE); + status = rdpei_recv_pdu(callback, data); return status; } diff --git a/channels/rdpgfx/client/CMakeLists.txt b/channels/rdpgfx/client/CMakeLists.txt index 2e76c8ced..dc47804ce 100644 --- a/channels/rdpgfx/client/CMakeLists.txt +++ b/channels/rdpgfx/client/CMakeLists.txt @@ -20,6 +20,8 @@ define_channel_client("rdpgfx") set(${MODULE_PREFIX}_SRCS rdpgfx_main.c rdpgfx_main.h + rdpgfx_codec.c + rdpgfx_codec.h rdpgfx_common.c rdpgfx_common.h) @@ -32,7 +34,7 @@ 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) + MODULES freerdp-common freerdp-codec freerdp-utils) set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} diff --git a/channels/rdpgfx/client/rdpgfx_codec.c b/channels/rdpgfx/client/rdpgfx_codec.c new file mode 100644 index 000000000..a749478a8 --- /dev/null +++ b/channels/rdpgfx/client/rdpgfx_codec.c @@ -0,0 +1,111 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Graphics Pipeline Extension + * + * Copyright 2014 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 "rdpgfx_codec.h" + +int rdpgfx_decode_uncompressed(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_remotefx(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + fprintf(stderr, "RdpGfxDecodeRemoteFx\n"); + + return 1; +} + +int rdpgfx_decode_clear(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_planar(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_h264(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_alpha(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_progressive(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode_progressive_v2(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + return 1; +} + +int rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) +{ + int status; + + switch (cmd->codecId) + { + case RDPGFX_CODECID_UNCOMPRESSED: + status = rdpgfx_decode_uncompressed(gfx, cmd); + break; + + case RDPGFX_CODECID_CAVIDEO: + status = rdpgfx_decode_remotefx(gfx, cmd); + break; + + case RDPGFX_CODECID_CLEARCODEC: + status = rdpgfx_decode_clear(gfx, cmd); + break; + + case RDPGFX_CODECID_PLANAR: + status = rdpgfx_decode_planar(gfx, cmd); + break; + + case RDPGFX_CODECID_H264: + status = rdpgfx_decode_h264(gfx, cmd); + break; + + case RDPGFX_CODECID_ALPHA: + status = rdpgfx_decode_alpha(gfx, cmd); + break; + + case RDPGFX_CODECID_CAPROGRESSIVE: + status = rdpgfx_decode_progressive(gfx, cmd); + break; + + case RDPGFX_CODECID_CAPROGRESSIVE_V2: + status = rdpgfx_decode_progressive_v2(gfx, cmd); + break; + } + + return 1; +} diff --git a/channels/sample/client/sample_main.h b/channels/rdpgfx/client/rdpgfx_codec.h similarity index 59% rename from channels/sample/client/sample_main.h rename to channels/rdpgfx/client/rdpgfx_codec.h index 865919135..51ff0d63f 100644 --- a/channels/sample/client/sample_main.h +++ b/channels/rdpgfx/client/rdpgfx_codec.h @@ -1,9 +1,8 @@ /** * FreeRDP: A Remote Desktop Protocol Implementation - * Sample Virtual Channel + * Graphics Pipeline Extension * - * Copyright 2012 Jay Sorg - * Copyright 2010-2012 Vic Lee + * Copyright 2014 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. @@ -18,9 +17,16 @@ * limitations under the License. */ -#ifndef __SAMPLE_MAIN_H -#define __SAMPLE_MAIN_H +#ifndef FREERDP_CHANNEL_RDPGFX_CLIENT_CODEC_H +#define FREERDP_CHANNEL_RDPGFX_CLIENT_CODEC_H -typedef struct sample_plugin samplePlugin; +#include +#include -#endif /* __SAMPLE_MAIN_H */ +#include + +#include "rdpgfx_main.h" + +int rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd); + +#endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_CODEC_H */ diff --git a/channels/rdpgfx/client/rdpgfx_common.c b/channels/rdpgfx/client/rdpgfx_common.c index c2ea76d7d..fde1f9325 100644 --- a/channels/rdpgfx/client/rdpgfx_common.c +++ b/channels/rdpgfx/client/rdpgfx_common.c @@ -26,12 +26,89 @@ #include "rdpgfx_common.h" -int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* point16) +const char* RDPGFX_CMDID_STRINGS[] = { - Stream_Read_UINT16(s, point16->x); /* x (2 bytes) */ - Stream_Read_UINT16(s, point16->y); /* y (2 bytes) */ + "RDPGFX_CMDID_UNUSED_0000", + "RDPGFX_CMDID_WIRETOSURFACE_1", + "RDPGFX_CMDID_WIRETOSURFACE_2", + "RDPGFX_CMDID_DELETEENCODINGCONTEXT", + "RDPGFX_CMDID_SOLIDFILL", + "RDPGFX_CMDID_SURFACETOSURFACE", + "RDPGFX_CMDID_SURFACETOCACHE", + "RDPGFX_CMDID_CACHETOSURFACE", + "RDPGFX_CMDID_EVICTCACHEENTRY", + "RDPGFX_CMDID_CREATESURFACE", + "RDPGFX_CMDID_DELETESURFACE", + "RDPGFX_CMDID_STARTFRAME", + "RDPGFX_CMDID_ENDFRAME", + "RDPGFX_CMDID_FRAMEACKNOWLEDGE", + "RDPGFX_CMDID_RESETGRAPHICS", + "RDPGFX_CMDID_MAPSURFACETOOUTPUT", + "RDPGFX_CMDID_CACHEIMPORTOFFER", + "RDPGFX_CMDID_CACHEIMPORTREPLY", + "RDPGFX_CMDID_CAPSADVERTISE", + "RDPGFX_CMDID_CAPSCONFIRM", + "RDPGFX_CMDID_UNUSED_0014", + "RDPGFX_CMDID_MAPSURFACETOWINDOW" +}; - return 0; +const char* rdpgfx_get_cmd_id_string(UINT16 cmdId) +{ + if (cmdId <= RDPGFX_CMDID_MAPSURFACETOWINDOW) + return RDPGFX_CMDID_STRINGS[cmdId]; + else + return "RDPGFX_CMDID_UNKNOWN"; +} + +const char* rdpgfx_get_codec_id_string(UINT16 codecId) +{ + switch (codecId) + { + case RDPGFX_CODECID_UNCOMPRESSED: + return "RDPGFX_CODECID_UNCOMPRESSED"; + case RDPGFX_CODECID_CAVIDEO: + return "RDPGFX_CODECID_CAVIDEO"; + case RDPGFX_CODECID_CLEARCODEC: + return "RDPGFX_CODECID_CLEARCODEC"; + case RDPGFX_CODECID_PLANAR: + return "RDPGFX_CODECID_PLANAR"; + case RDPGFX_CODECID_H264: + return "RDPGFX_CODECID_H264"; + case RDPGFX_CODECID_ALPHA: + return "RDPGFX_CODECID_ALPHA"; + case RDPGFX_CODECID_CAPROGRESSIVE: + return "RDPGFX_CODECID_CAPROGRESSIVE"; + case RDPGFX_CODECID_CAPROGRESSIVE_V2: + return "RDPGFX_CODECID_CAPROGRESSIVE_V2"; + } + + return "RDPGFX_CODECID_UNKNOWN"; +} + +int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header) +{ + Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ + Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */ + Stream_Read_UINT32(s, header->pduLength); /* pduLength (4 bytes) */ + + return 1; +} + +int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header) +{ + Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ + Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */ + Stream_Write_UINT32(s, header->pduLength); /* pduLength (4 bytes) */ + + return 1; +} + +int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16) +{ + Stream_Read_UINT16(s, pt16->x); /* x (2 bytes) */ + Stream_Read_UINT16(s, pt16->y); /* y (2 bytes) */ + + return 1; } int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16) @@ -39,7 +116,7 @@ int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16) Stream_Write_UINT16(s, point16->x); /* x (2 bytes) */ Stream_Write_UINT16(s, point16->y); /* y (2 bytes) */ - return 0; + return 1; } int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16) @@ -49,7 +126,7 @@ int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16) Stream_Read_UINT16(s, rect16->right); /* right (2 bytes) */ Stream_Read_UINT16(s, rect16->bottom); /* bottom (2 bytes) */ - return 0; + return 1; } int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16) @@ -59,7 +136,7 @@ int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16) Stream_Write_UINT16(s, rect16->right); /* right (2 bytes) */ Stream_Write_UINT16(s, rect16->bottom); /* bottom (2 bytes) */ - return 0; + return 1; } int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32) @@ -69,7 +146,7 @@ int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32) Stream_Read_UINT8(s, color32->R); /* R (1 byte) */ Stream_Read_UINT8(s, color32->XA); /* XA (1 byte) */ - return 0; + return 1; } int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32) @@ -79,23 +156,5 @@ int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32) Stream_Write_UINT8(s, color32->R); /* R (1 byte) */ Stream_Write_UINT8(s, color32->XA); /* XA (1 byte) */ - return 0; -} - -int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header) -{ - Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ - Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */ - Stream_Read_UINT16(s, header->pduLength); /* pduLength (4 bytes) */ - - return 0; -} - -int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header) -{ - Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */ - Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */ - Stream_Write_UINT16(s, header->pduLength); /* pduLength (4 bytes) */ - - return 0; + return 1; } diff --git a/channels/rdpgfx/client/rdpgfx_common.h b/channels/rdpgfx/client/rdpgfx_common.h index df80c2af6..d2b1ea1d4 100644 --- a/channels/rdpgfx/client/rdpgfx_common.h +++ b/channels/rdpgfx/client/rdpgfx_common.h @@ -25,14 +25,20 @@ #include -int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* point16); -int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16); -int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16); -int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16); -int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32); -int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32); +const char* rdpgfx_get_cmd_id_string(UINT16 cmdId); +const char* rdpgfx_get_codec_id_string(UINT16 codecId); + int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header); int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header); +int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16); +int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16); + +int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16); +int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16); + +int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32); +int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32); + #endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_COMMON_H */ diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 8c6d52b84..032b51b81 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -2,7 +2,7 @@ * FreeRDP: A Remote Desktop Protocol Implementation * Graphics Pipeline Extension * - * Copyright 2013 Marc-Andre Moreau + * Copyright 2013-2014 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. @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -38,63 +39,764 @@ #include #include "rdpgfx_common.h" +#include "rdpgfx_codec.h" #include "rdpgfx_main.h" -struct _RDPGFX_CHANNEL_CALLBACK +int rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) { - IWTSVirtualChannelCallback iface; + int status; + wStream* s; + UINT16 index; + RDPGFX_PLUGIN* gfx; + RDPGFX_HEADER header; + RDPGFX_CAPSET* capsSet; + RDPGFX_CAPSET capsSets[2]; + RDPGFX_CAPS_ADVERTISE_PDU pdu; - IWTSPlugin* plugin; - IWTSVirtualChannelManager* channel_mgr; - IWTSVirtualChannel* channel; -}; -typedef struct _RDPGFX_CHANNEL_CALLBACK RDPGFX_CHANNEL_CALLBACK; + gfx = (RDPGFX_PLUGIN*) callback->plugin; -struct _RDPGFX_LISTENER_CALLBACK + gfx->ThinClient = TRUE; + gfx->SmallCache = FALSE; + gfx->H264 = FALSE; + + gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600; + + header.flags = 0; + header.cmdId = RDPGFX_CMDID_CAPSADVERTISE; + + pdu.capsSetCount = 1; + pdu.capsSets = (RDPGFX_CAPSET*) capsSets; + + capsSet = &capsSets[0]; + + capsSet->version = RDPGFX_CAPVERSION_8; + capsSet->flags = 0; + + if (gfx->ThinClient) + capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; + + if (gfx->SmallCache) + capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + + capsSet = &capsSets[1]; + + capsSet->version = RDPGFX_CAPVERSION_81; + capsSet->flags = 0; + + if (gfx->ThinClient) + capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; + + if (gfx->SmallCache) + capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + + if (gfx->H264) + capsSet->flags |= RDPGFX_CAPS_FLAG_H264ENABLED; + + header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE); + + WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu"); + + s = Stream_New(NULL, header.pduLength); + + rdpgfx_write_header(s, &header); + + /* RDPGFX_CAPS_ADVERTISE_PDU */ + + Stream_Write_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */ + + for (index = 0; index < pdu.capsSetCount; index++) + { + capsSet = &(pdu.capsSets[index]); + Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */ + Stream_Write_UINT32(s, 4); /* capsDataLength (4 bytes) */ + Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */ + } + + Stream_SealLength(s); + + status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); + + Stream_Free(s, TRUE); + + return status; +} + +int rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { - IWTSListenerCallback iface; + RDPGFX_CAPSET capsSet; + UINT32 capsDataLength; + RDPGFX_CAPS_CONFIRM_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; - IWTSPlugin* plugin; - IWTSVirtualChannelManager* channel_mgr; - RDPGFX_CHANNEL_CALLBACK* channel_callback; -}; -typedef struct _RDPGFX_LISTENER_CALLBACK RDPGFX_LISTENER_CALLBACK; + pdu.capsSet = &capsSet; -struct _RDPGFX_PLUGIN + Stream_Read_UINT32(s, capsSet.version); /* version (4 bytes) */ + Stream_Read_UINT32(s, capsDataLength); /* capsDataLength (4 bytes) */ + Stream_Read_UINT32(s, capsSet.flags); /* capsData (4 bytes) */ + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvCapsConfirmPdu: version: 0x%04X flags: 0x%04X", + capsSet.version, capsSet.flags); + + return 1; +} + +int rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, RDPGFX_FRAME_ACKNOWLEDGE_PDU* pdu) { - IWTSPlugin iface; + int status; + wStream* s; + RDPGFX_HEADER header; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; - IWTSListener* listener; - RDPGFX_LISTENER_CALLBACK* listener_callback; -}; -typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; + header.flags = 0; + header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE; + header.pduLength = RDPGFX_HEADER_SIZE + 12; + + WLog_Print(gfx->log, WLOG_DEBUG, "SendFrameAcknowledgePdu: %d", pdu->frameId); + + s = Stream_New(NULL, header.pduLength); + + rdpgfx_write_header(s, &header); + + /* RDPGFX_FRAME_ACKNOWLEDGE_PDU */ + + Stream_Write_UINT32(s, pdu->queueDepth); /* queueDepth (4 bytes) */ + Stream_Write_UINT32(s, pdu->frameId); /* frameId (4 bytes) */ + Stream_Write_UINT32(s, pdu->totalFramesDecoded); /* totalFramesDecoded (4 bytes) */ + + status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); + + Stream_Free(s, TRUE); + + return status; +} + +int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + int pad; + UINT32 index; + MONITOR_DEF* monitor; + RDPGFX_RESET_GRAPHICS_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT32(s, pdu.width); /* width (4 bytes) */ + Stream_Read_UINT32(s, pdu.height); /* height (4 bytes) */ + Stream_Read_UINT32(s, pdu.monitorCount); /* monitorCount (4 bytes) */ + + pdu.monitorDefArray = (MONITOR_DEF*) calloc(pdu.monitorCount, sizeof(MONITOR_DEF)); + + if (!pdu.monitorDefArray) + return -1; + + for (index = 0; index < pdu.monitorCount; index++) + { + monitor = &(pdu.monitorDefArray[index]); + Stream_Read_UINT32(s, monitor->left); /* left (4 bytes) */ + Stream_Read_UINT32(s, monitor->top); /* top (4 bytes) */ + Stream_Read_UINT32(s, monitor->right); /* right (4 bytes) */ + Stream_Read_UINT32(s, monitor->bottom); /* bottom (4 bytes) */ + Stream_Read_UINT32(s, monitor->flags); /* flags (4 bytes) */ + } + + pad = 340 - (RDPGFX_HEADER_SIZE + 12 + (pdu.monitorCount * 20)); + Stream_Seek(s, pad); /* pad (total size is 340 bytes) */ + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvResetGraphicsPdu: width: %d height: %d count: %d", + pdu.width, pdu.height, pdu.monitorCount); + + if (context && context->ResetGraphics) + { + context->ResetGraphics(context, &pdu); + } + + free(pdu.monitorDefArray); + + return 1; +} + +int rdpgfx_recv_evict_cache_entry_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_EVICT_CACHE_ENTRY_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvEvictCacheEntryPdu: cacheSlot: %d", pdu.cacheSlot); + + if (context && context->EvictCacheEntry) + { + context->EvictCacheEntry(context, &pdu); + } + + return 1; +} + +int rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + UINT16 index; + RDPGFX_CACHE_IMPORT_REPLY_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.importedEntriesCount); /* cacheSlot (2 bytes) */ + + pdu.cacheSlots = (UINT16*) calloc(pdu.importedEntriesCount, sizeof(UINT16)); + + if (!pdu.cacheSlots) + return -1; + + for (index = 0; index < pdu.importedEntriesCount; index++) + { + Stream_Read_UINT16(s, pdu.cacheSlots[index]); /* cacheSlot (2 bytes) */ + } + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvCacheImportReplyPdu: importedEntriesCount: %d", + pdu.importedEntriesCount); + + if (context && context->CacheImportReply) + { + context->CacheImportReply(context, &pdu); + } + + return 1; +} + +int rdpgfx_recv_create_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_CREATE_SURFACE_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT16(s, pdu.width); /* width (2 bytes) */ + Stream_Read_UINT16(s, pdu.height); /* height (2 bytes) */ + Stream_Read_UINT8(s, pdu.pixelFormat); /* RDPGFX_PIXELFORMAT (1 byte) */ + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvCreateSurfacePdu: surfaceId: %d width: %d height: %d pixelFormat: 0x%02X", + pdu.surfaceId, pdu.width, pdu.height, pdu.pixelFormat); + + if (context && context->CreateSurface) + { + context->CreateSurface(context, &pdu); + } + + return 1; +} + +int rdpgfx_recv_delete_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_DELETE_SURFACE_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvDeleteSurfacePdu: surfaceId: %d", pdu.surfaceId); + + if (context && context->DeleteSurface) + { + context->DeleteSurface(context, &pdu); + } + + return 1; +} + +int rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_START_FRAME_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT32(s, pdu.timestamp); /* timestamp (4 bytes) */ + Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvStartFramePdu: frameId: %d timestamp: 0x%04X\n", + pdu.frameId, pdu.timestamp); + + if (context && context->StartFrame) + { + context->StartFrame(context, &pdu); + } + + gfx->UnacknowledgedFrames++; + + return 1; +} + +int rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_END_FRAME_PDU pdu; + RDPGFX_FRAME_ACKNOWLEDGE_PDU ack; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */ + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvEndFramePdu: frameId: %d\n", pdu.frameId); + + if (context && context->EndFrame) + { + context->EndFrame(context, &pdu); + } + + gfx->UnacknowledgedFrames--; + gfx->TotalDecodedFrames++; + + ack.frameId = pdu.frameId; + ack.totalFramesDecoded = gfx->TotalDecodedFrames; + + //ack.queueDepth = SUSPEND_FRAME_ACKNOWLEDGEMENT; + ack.queueDepth = QUEUE_DEPTH_UNAVAILABLE; + + rdpgfx_send_frame_acknowledge_pdu(callback, &ack); + + return 1; +} + +int rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_SURFACE_COMMAND cmd; + RDPGFX_WIRE_TO_SURFACE_PDU_1 pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT16(s, pdu.codecId); /* codecId (2 bytes) */ + Stream_Read_UINT8(s, pdu.pixelFormat); /* pixelFormat (1 byte) */ + + rdpgfx_read_rect16(s, &(pdu.destRect)); /* destRect (8 bytes) */ + + Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ + + if (pdu.bitmapDataLength > Stream_GetRemainingLength(s)) + return -1; + + pdu.bitmapData = Stream_Pointer(s); + Stream_Seek(s, pdu.bitmapDataLength); + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvWireToSurface1Pdu: surfaceId: %d codecId: %s (0x%04X) pixelFormat: 0x%04X " + "destRect: left: %d top: %d right: %d bottom: %d bitmapDataLength: %d", + (int) pdu.surfaceId, rdpgfx_get_codec_id_string(pdu.codecId), pdu.codecId, pdu.pixelFormat, + pdu.destRect.left, pdu.destRect.top, pdu.destRect.right, pdu.destRect.bottom, + pdu.bitmapDataLength); + + cmd.surfaceId = pdu.surfaceId; + cmd.codecId = pdu.codecId; + cmd.contextId = 0; + cmd.format = pdu.pixelFormat; + cmd.left = pdu.destRect.left; + cmd.top = pdu.destRect.top; + cmd.right = pdu.destRect.right; + cmd.bottom = pdu.destRect.bottom; + cmd.width = cmd.right - cmd.left; + cmd.height = cmd.bottom - cmd.top; + cmd.length = pdu.bitmapDataLength; + cmd.data = pdu.bitmapData; + + if (context && context->SurfaceCommand) + { + context->SurfaceCommand(context, &cmd); + } + + return 1; +} + +int rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_SURFACE_COMMAND cmd; + RDPGFX_WIRE_TO_SURFACE_PDU_2 pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT16(s, pdu.codecId); /* codecId (2 bytes) */ + Stream_Read_UINT32(s, pdu.codecContextId); /* codecContextId (4 bytes) */ + Stream_Read_UINT8(s, pdu.pixelFormat); /* pixelFormat (1 byte) */ + + Stream_Read_UINT32(s, pdu.bitmapDataLength); /* bitmapDataLength (4 bytes) */ + + pdu.bitmapData = Stream_Pointer(s); + Stream_Seek(s, pdu.bitmapDataLength); + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvWireToSurface2Pdu: surfaceId: %d codecId: 0x%04X " + "codecContextId: %d pixelFormat: 0x%04X bitmapDataLength: %d", + (int) pdu.surfaceId, pdu.codecId, pdu.codecContextId, pdu.pixelFormat, pdu.bitmapDataLength); + + cmd.surfaceId = pdu.surfaceId; + cmd.codecId = pdu.codecId; + cmd.contextId = pdu.codecContextId; + cmd.format = pdu.pixelFormat; + cmd.left = 0; + cmd.top = 0; + cmd.right = 0; + cmd.bottom = 0; + cmd.width = 0; + cmd.height = 0; + cmd.length = pdu.bitmapDataLength; + cmd.data = pdu.bitmapData; + + if (context && context->SurfaceCommand) + { + context->SurfaceCommand(context, &cmd); + } + + return 1; +} + +int rdpgfx_recv_delete_encoding_context_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_DELETE_ENCODING_CONTEXT_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT32(s, pdu.codecContextId); /* codecContextId (4 bytes) */ + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvDeleteEncodingContextPdu: surfaceId: %d codecContextId: %d", + pdu.surfaceId, pdu.codecContextId); + + if (context && context->DeleteEncodingContext) + { + context->DeleteEncodingContext(context, &pdu); + } + + return 1; +} + +int rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + UINT16 index; + RDPGFX_RECT16* fillRect; + RDPGFX_SOLID_FILL_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + + rdpgfx_read_color32(s, &(pdu.fillPixel)); /* fillPixel (4 bytes) */ + + Stream_Read_UINT16(s, pdu.fillRectCount); /* fillRectCount (2 bytes) */ + + pdu.fillRects = (RDPGFX_RECT16*) calloc(pdu.fillRectCount, sizeof(RDPGFX_RECT16)); + + if (!pdu.fillRects) + return -1; + + for (index = 0; index < pdu.fillRectCount; index++) + { + fillRect = &(pdu.fillRects[index]); + rdpgfx_read_rect16(s, fillRect); + } + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvSolidFillPdu: surfaceId: %d fillRectCount: %d", + pdu.surfaceId, pdu.fillRectCount); + + if (context && context->SolidFill) + { + context->SolidFill(context, &pdu); + } + + return 1; +} + +int rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + UINT16 index; + RDPGFX_POINT16* destPt; + RDPGFX_SURFACE_TO_SURFACE_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.surfaceIdSrc); /* surfaceIdSrc (2 bytes) */ + Stream_Read_UINT16(s, pdu.surfaceIdDest); /* surfaceIdDest (2 bytes) */ + + rdpgfx_read_rect16(s, &(pdu.rectSrc)); /* rectSrc (8 bytes ) */ + + Stream_Read_UINT16(s, pdu.destPtsCount); /* destPtsCount (2 bytes) */ + + pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16)); + + if (!pdu.destPts) + return -1; + + for (index = 0; index < pdu.destPtsCount; index++) + { + destPt = &(pdu.destPts[index]); + rdpgfx_read_point16(s, destPt); + } + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvSurfaceToSurfacePdu: surfaceIdSrc: %d surfaceIdDest: %d " + "left: %d top: %d right: %d bottom: %d destPtsCount: %d", + pdu.surfaceIdSrc, pdu.surfaceIdDest, + pdu.rectSrc.left, pdu.rectSrc.top, pdu.rectSrc.right, pdu.rectSrc.bottom, + pdu.destPtsCount); + + if (context && context->SurfaceToSurface) + { + context->SurfaceToSurface(context, &pdu); + } + + return 1; +} + +int rdpgfx_recv_surface_to_cache_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_SURFACE_TO_CACHE_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT64(s, pdu.cacheKey); /* cacheKey (8 bytes) */ + Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ + rdpgfx_read_rect16(s, &(pdu.rectSrc)); /* rectSrc (8 bytes ) */ + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvSurfaceToCachePdu: surfaceId: %d cacheKey: 0x%08X cacheSlot: %d " + "left: %d top: %d right: %d bottom: %d", + pdu.surfaceId, (int) pdu.cacheKey, pdu.cacheSlot, + pdu.rectSrc.left, pdu.rectSrc.top, + pdu.rectSrc.right, pdu.rectSrc.bottom); + + if (context && context->SurfaceToCache) + { + context->SurfaceToCache(context, &pdu); + } + + return 1; +} + +int rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + UINT16 index; + RDPGFX_POINT16* destPt; + RDPGFX_CACHE_TO_SURFACE_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.cacheSlot); /* cacheSlot (2 bytes) */ + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT16(s, pdu.destPtsCount); /* destPtsCount (2 bytes) */ + + pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16)); + + if (!pdu.destPts) + return -1; + + for (index = 0; index < pdu.destPtsCount; index++) + { + destPt = &(pdu.destPts[index]); + rdpgfx_read_point16(s, destPt); + } + + WLog_Print(gfx->log, WLOG_DEBUG, "RdpGfxRecvCacheToSurfacePdu: cacheSlot: %d surfaceId: %d destPtsCount: %d", + pdu.cacheSlot, (int) pdu.surfaceId, pdu.destPtsCount); + + if (context && context->CacheToSurface) + { + context->CacheToSurface(context, &pdu); + } + + free(pdu.destPts); + + return 1; +} + +int rdpgfx_recv_map_surface_to_output_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT16(s, pdu.reserved); /* reserved (2 bytes) */ + Stream_Read_UINT32(s, pdu.outputOriginX); /* outputOriginX (4 bytes) */ + Stream_Read_UINT32(s, pdu.outputOriginY); /* outputOriginY (4 bytes) */ + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvMapSurfaceToOutputPdu: surfaceId: %d outputOriginX: %d outputOriginY: %d", + (int) pdu.surfaceId, pdu.outputOriginX, pdu.outputOriginY); + + if (context && context->MapSurfaceToOutput) + { + context->MapSurfaceToOutput(context, &pdu); + } + + return 1; +} + +int rdpgfx_recv_map_surface_to_window_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) +{ + RDPGFX_MAP_SURFACE_TO_WINDOW_PDU pdu; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + + Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */ + Stream_Read_UINT64(s, pdu.windowId); /* windowId (8 bytes) */ + Stream_Read_UINT32(s, pdu.mappedWidth); /* mappedWidth (4 bytes) */ + Stream_Read_UINT32(s, pdu.mappedHeight); /* mappedHeight (4 bytes) */ + + WLog_Print(gfx->log, WLOG_DEBUG, "RecvMapSurfaceToWindowPdu: surfaceId: %d windowId: 0x%04X mappedWidth: %d mappedHeight: %d", + pdu.surfaceId, (int) pdu.windowId, pdu.mappedWidth, pdu.mappedHeight); + + if (context && context->MapSurfaceToWindow) + { + context->MapSurfaceToWindow(context, &pdu); + } + + return 1; +} int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { - return 0; + int status; + int beg, end; + RDPGFX_HEADER header; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + + beg = Stream_GetPosition(s); + + rdpgfx_read_header(s, &header); + +#if 1 + WLog_Print(gfx->log, WLOG_DEBUG, "cmdId: %s (0x%04X) flags: 0x%04X pduLength: %d", + rdpgfx_get_cmd_id_string(header.cmdId), header.cmdId, header.flags, header.pduLength); +#endif + + switch (header.cmdId) + { + case RDPGFX_CMDID_WIRETOSURFACE_1: + status = rdpgfx_recv_wire_to_surface_1_pdu(callback, s); + break; + + case RDPGFX_CMDID_WIRETOSURFACE_2: + status = rdpgfx_recv_wire_to_surface_2_pdu(callback, s); + break; + + case RDPGFX_CMDID_DELETEENCODINGCONTEXT: + status = rdpgfx_recv_delete_encoding_context_pdu(callback, s); + break; + + case RDPGFX_CMDID_SOLIDFILL: + status = rdpgfx_recv_solid_fill_pdu(callback, s); + break; + + case RDPGFX_CMDID_SURFACETOSURFACE: + status = rdpgfx_recv_surface_to_surface_pdu(callback, s); + break; + + case RDPGFX_CMDID_SURFACETOCACHE: + status = rdpgfx_recv_surface_to_cache_pdu(callback, s); + break; + + case RDPGFX_CMDID_CACHETOSURFACE: + status = rdpgfx_recv_cache_to_surface_pdu(callback, s); + break; + + case RDPGFX_CMDID_EVICTCACHEENTRY: + status = rdpgfx_recv_evict_cache_entry_pdu(callback, s); + break; + + case RDPGFX_CMDID_CREATESURFACE: + status = rdpgfx_recv_create_surface_pdu(callback, s); + break; + + case RDPGFX_CMDID_DELETESURFACE: + status = rdpgfx_recv_delete_surface_pdu(callback, s); + break; + + case RDPGFX_CMDID_STARTFRAME: + status = rdpgfx_recv_start_frame_pdu(callback, s); + break; + + case RDPGFX_CMDID_ENDFRAME: + status = rdpgfx_recv_end_frame_pdu(callback, s); + break; + + case RDPGFX_CMDID_RESETGRAPHICS: + status = rdpgfx_recv_reset_graphics_pdu(callback, s); + break; + + case RDPGFX_CMDID_MAPSURFACETOOUTPUT: + status = rdpgfx_recv_map_surface_to_output_pdu(callback, s); + break; + + case RDPGFX_CMDID_CACHEIMPORTREPLY: + status = rdpgfx_recv_cache_import_reply_pdu(callback, s); + break; + + case RDPGFX_CMDID_CAPSCONFIRM: + status = rdpgfx_recv_caps_confirm_pdu(callback, s); + break; + + case RDPGFX_CMDID_MAPSURFACETOWINDOW: + status = rdpgfx_recv_map_surface_to_window_pdu(callback, s); + break; + + default: + fprintf(stderr, "Unknown GFX cmdId: 0x%04X\n", header.cmdId); + break; + } + + end = Stream_GetPosition(s); + + if (end != (beg + header.pduLength)) + { + fprintf(stderr, "Unexpected gfx pdu end: Actual: %d, Expected: %d\n", + end, (beg + header.pduLength)); + + Stream_SetPosition(s, (beg + header.pduLength)); + } + + return status; } -static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer) +static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data) { wStream* s; int status = 0; + UINT32 DstSize = 0; + BYTE* pDstData = NULL; RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; - fprintf(stderr, "RdpGfxOnDataReceived\n"); + status = zgfx_decompress(gfx->zgfx, Stream_Pointer(data), Stream_GetRemainingLength(data), &pDstData, &DstSize, 0); - s = Stream_New(pBuffer, cbSize); + if (status < 0) + { + printf("zgfx_decompress failure! status: %d\n", status); + return 0; + } - status = rdpgfx_recv_pdu(callback, s); + s = Stream_New(pDstData, DstSize); - Stream_Free(s, FALSE); + while (Stream_GetPosition(s) < Stream_Length(s)) + { + status = rdpgfx_recv_pdu(callback, s); + } + + Stream_Free(s, TRUE); return status; } +static int rdpgfx_on_open(IWTSVirtualChannelCallback* pChannelCallback) +{ + RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + + WLog_Print(gfx->log, WLOG_DEBUG, "OnOpen"); + + rdpgfx_send_caps_advertise_pdu(callback); + + return 0; +} + static int rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback) { RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + + WLog_Print(gfx->log, WLOG_DEBUG, "OnClose"); free(callback); @@ -108,10 +810,13 @@ static int rdpgfx_on_new_channel_connection(IWTSListenerCallback* pListenerCallb RDPGFX_CHANNEL_CALLBACK* callback; RDPGFX_LISTENER_CALLBACK* listener_callback = (RDPGFX_LISTENER_CALLBACK*) pListenerCallback; - callback = (RDPGFX_CHANNEL_CALLBACK*) malloc(sizeof(RDPGFX_CHANNEL_CALLBACK)); - ZeroMemory(callback, sizeof(RDPGFX_CHANNEL_CALLBACK)); + callback = (RDPGFX_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPGFX_CHANNEL_CALLBACK)); + + if (!callback) + return -1; callback->iface.OnDataReceived = rdpgfx_on_data_received; + callback->iface.OnOpen = rdpgfx_on_open; callback->iface.OnClose = rdpgfx_on_close; callback->plugin = listener_callback->plugin; callback->channel_mgr = listener_callback->channel_mgr; @@ -120,53 +825,139 @@ static int rdpgfx_on_new_channel_connection(IWTSListenerCallback* pListenerCallb *ppCallback = (IWTSVirtualChannelCallback*) callback; - fprintf(stderr, "RdpGfxOnNewChannelConnection\n"); - return 0; } static int rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { int status; - RDPGFX_PLUGIN* rdpgfx = (RDPGFX_PLUGIN*) pPlugin; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) pPlugin; - rdpgfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) malloc(sizeof(RDPGFX_LISTENER_CALLBACK)); - ZeroMemory(rdpgfx->listener_callback, sizeof(RDPGFX_LISTENER_CALLBACK)); + gfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) calloc(1, sizeof(RDPGFX_LISTENER_CALLBACK)); - rdpgfx->listener_callback->iface.OnNewChannelConnection = rdpgfx_on_new_channel_connection; - rdpgfx->listener_callback->plugin = pPlugin; - rdpgfx->listener_callback->channel_mgr = pChannelMgr; + if (!gfx->listener_callback) + return -1; + + gfx->listener_callback->iface.OnNewChannelConnection = rdpgfx_on_new_channel_connection; + gfx->listener_callback->plugin = pPlugin; + gfx->listener_callback->channel_mgr = pChannelMgr; status = pChannelMgr->CreateListener(pChannelMgr, RDPGFX_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*) rdpgfx->listener_callback, &(rdpgfx->listener)); + (IWTSListenerCallback*) gfx->listener_callback, &(gfx->listener)); - rdpgfx->listener->pInterface = rdpgfx->iface.pInterface; + gfx->listener->pInterface = gfx->iface.pInterface; - fprintf(stderr, "RdpGfxInitialize\n"); + WLog_Print(gfx->log, WLOG_DEBUG, "Initialize"); return status; } static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin) { - RDPGFX_PLUGIN* rdpgfx = (RDPGFX_PLUGIN*) pPlugin; + int count; + int index; + ULONG_PTR* pKeys = NULL; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) pPlugin; + RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; - if (rdpgfx->listener_callback) - free(rdpgfx->listener_callback); + WLog_Print(gfx->log, WLOG_DEBUG, "Terminated"); - free(rdpgfx); + if (gfx->listener_callback) + free(gfx->listener_callback); + + zgfx_context_free(gfx->zgfx); + + count = HashTable_GetKeys(gfx->SurfaceTable, &pKeys); + + for (index = 0; index < count; index++) + { + RDPGFX_DELETE_SURFACE_PDU pdu; + + pdu.surfaceId = ((UINT16) pKeys[index]) - 1; + + if (context && context->DeleteSurface) + { + context->DeleteSurface(context, &pdu); + } + } + + free(pKeys); + + HashTable_Free(gfx->SurfaceTable); + + for (index = 0; index < gfx->MaxCacheSlot; index++) + { + if (gfx->CacheSlots[index]) + { + RDPGFX_EVICT_CACHE_ENTRY_PDU pdu; + + pdu.cacheSlot = (UINT16) index; + + if (context && context->EvictCacheEntry) + { + context->EvictCacheEntry(context, &pdu); + } + + gfx->CacheSlots[index] = NULL; + } + } + + free(gfx); return 0; } -/** - * Channel Client Interface - */ - -UINT32 rdpgfx_get_version(RdpgfxClientContext* context) +int rdpgfx_set_surface_data(RdpgfxClientContext* context, UINT16 surfaceId, void* pData) { - //RDPGFX_PLUGIN* rdpgfx = (RDPGFX_PLUGIN*) context->handle; - return 0; + ULONG_PTR key; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; + + key = ((ULONG_PTR) surfaceId) + 1; + + if (pData) + HashTable_Add(gfx->SurfaceTable, (void*) key, pData); + else + HashTable_Remove(gfx->SurfaceTable, (void*) key); + + return 1; +} + +void* rdpgfx_get_surface_data(RdpgfxClientContext* context, UINT16 surfaceId) +{ + ULONG_PTR key; + void* pData = NULL; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; + + key = ((ULONG_PTR) surfaceId) + 1; + + pData = HashTable_GetItemValue(gfx->SurfaceTable, (void*) key); + + return pData; +} + +int rdpgfx_set_cache_slot_data(RdpgfxClientContext* context, UINT16 cacheSlot, void* pData) +{ + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; + + if (cacheSlot >= gfx->MaxCacheSlot) + return -1; + + gfx->CacheSlots[cacheSlot] = pData; + + return 1; +} + +void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cacheSlot) +{ + void* pData = NULL; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) context->handle; + + if (cacheSlot >= gfx->MaxCacheSlot) + return NULL; + + pData = gfx->CacheSlots[cacheSlot]; + + return pData; } #ifdef STATIC_CHANNELS @@ -175,33 +966,52 @@ UINT32 rdpgfx_get_version(RdpgfxClientContext* context) int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - int error = 0; - RDPGFX_PLUGIN* rdpgfx; + int status = 0; + RDPGFX_PLUGIN* gfx; RdpgfxClientContext* context; - rdpgfx = (RDPGFX_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "rdpgfx"); + gfx = (RDPGFX_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "rdpgfx"); - if (!rdpgfx) + if (!gfx) { - rdpgfx = (RDPGFX_PLUGIN*) malloc(sizeof(RDPGFX_PLUGIN)); - ZeroMemory(rdpgfx, sizeof(RDPGFX_PLUGIN)); + gfx = (RDPGFX_PLUGIN*) calloc(1, sizeof(RDPGFX_PLUGIN)); - rdpgfx->iface.Initialize = rdpgfx_plugin_initialize; - rdpgfx->iface.Connected = NULL; - rdpgfx->iface.Disconnected = NULL; - rdpgfx->iface.Terminated = rdpgfx_plugin_terminated; + if (!gfx) + return -1; - context = (RdpgfxClientContext*) malloc(sizeof(RdpgfxClientContext)); + gfx->log = WLog_Get("com.freerdp.gfx.client"); - context->handle = (void*) rdpgfx; - context->GetVersion = rdpgfx_get_version; + gfx->iface.Initialize = rdpgfx_plugin_initialize; + gfx->iface.Connected = NULL; + gfx->iface.Disconnected = NULL; + gfx->iface.Terminated = rdpgfx_plugin_terminated; - rdpgfx->iface.pInterface = (void*) context; + gfx->SurfaceTable = HashTable_New(TRUE); - fprintf(stderr, "RdpGfxDVCPluginEntry\n"); + if (!gfx->SurfaceTable) + return -1; - error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpgfx", (IWTSPlugin*) rdpgfx); + gfx->ThinClient = TRUE; + gfx->MaxCacheSlot = (gfx->ThinClient) ? 4096 : 25600; + + context = (RdpgfxClientContext*) calloc(1, sizeof(RdpgfxClientContext)); + + if (!context) + return -1; + + context->handle = (void*) gfx; + + context->SetSurfaceData = rdpgfx_set_surface_data; + context->GetSurfaceData = rdpgfx_get_surface_data; + context->SetCacheSlotData = rdpgfx_set_cache_slot_data; + context->GetCacheSlotData = rdpgfx_get_cache_slot_data; + + gfx->iface.pInterface = (void*) context; + + gfx->zgfx = zgfx_context_new(FALSE); + + status = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpgfx", (IWTSPlugin*) gfx); } - return error; + return status; } diff --git a/channels/rdpgfx/client/rdpgfx_main.h b/channels/rdpgfx/client/rdpgfx_main.h index 74cfcbef3..e1dc362ea 100644 --- a/channels/rdpgfx/client/rdpgfx_main.h +++ b/channels/rdpgfx/client/rdpgfx_main.h @@ -2,7 +2,7 @@ * FreeRDP: A Remote Desktop Protocol Implementation * Graphics Pipeline Extension * - * Copyright 2013 Marc-Andre Moreau + * Copyright 2013-2014 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. @@ -20,17 +20,60 @@ #ifndef FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H #define FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include #include #include +#include +#include + #include +#include +struct _RDPGFX_CHANNEL_CALLBACK +{ + IWTSVirtualChannelCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; + IWTSVirtualChannel* channel; +}; +typedef struct _RDPGFX_CHANNEL_CALLBACK RDPGFX_CHANNEL_CALLBACK; + +struct _RDPGFX_LISTENER_CALLBACK +{ + IWTSListenerCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; + RDPGFX_CHANNEL_CALLBACK* channel_callback; +}; +typedef struct _RDPGFX_LISTENER_CALLBACK RDPGFX_LISTENER_CALLBACK; + +struct _RDPGFX_PLUGIN +{ + IWTSPlugin iface; + + IWTSListener* listener; + RDPGFX_LISTENER_CALLBACK* listener_callback; + + wLog* log; + + BOOL ThinClient; + BOOL SmallCache; + BOOL H264; + + ZGFX_CONTEXT* zgfx; + UINT32 UnacknowledgedFrames; + UINT32 TotalDecodedFrames; + + wHashTable* SurfaceTable; + + UINT16 MaxCacheSlot; + void* CacheSlots[25600]; +}; +typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; #endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H */ diff --git a/channels/rdpsnd/client/ios/rdpsnd_ios.c b/channels/rdpsnd/client/ios/rdpsnd_ios.c index 60da43cc1..1adcc3eee 100644 --- a/channels/rdpsnd/client/ios/rdpsnd_ios.c +++ b/channels/rdpsnd/client/ios/rdpsnd_ios.c @@ -20,12 +20,11 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif - + #include #include #include -#include #import @@ -37,66 +36,66 @@ typedef struct rdpsnd_ios_plugin { - rdpsndDevicePlugin device; - AudioComponentInstance audio_unit; - TPCircularBuffer buffer; - BOOL is_opened; - BOOL is_playing; + rdpsndDevicePlugin device; + AudioComponentInstance audio_unit; + TPCircularBuffer buffer; + BOOL is_opened; + BOOL is_playing; } rdpsndIOSPlugin; #define THIS(__ptr) ((rdpsndIOSPlugin*)__ptr) static OSStatus rdpsnd_ios_render_cb( - void *inRefCon, - AudioUnitRenderActionFlags __unused *ioActionFlags, - const AudioTimeStamp __unused *inTimeStamp, - UInt32 inBusNumber, - UInt32 __unused inNumberFrames, - AudioBufferList *ioData + void *inRefCon, + AudioUnitRenderActionFlags __unused *ioActionFlags, + const AudioTimeStamp __unused *inTimeStamp, + UInt32 inBusNumber, + UInt32 __unused inNumberFrames, + AudioBufferList *ioData ) { - unsigned int i; - - if (inBusNumber != 0) - { - return noErr; - } - - rdpsndIOSPlugin *p = THIS(inRefCon); - - for (i = 0; i < ioData->mNumberBuffers; i++) - { - AudioBuffer* target_buffer = &ioData->mBuffers[i]; - - int32_t available_bytes = 0; - const void *buffer = TPCircularBufferTail(&p->buffer, &available_bytes); - if (buffer != NULL && available_bytes > 0) - { - const int bytes_to_copy = MIN((int32_t)target_buffer->mDataByteSize, available_bytes); - - memcpy(target_buffer->mData, buffer, bytes_to_copy); - target_buffer->mDataByteSize = bytes_to_copy; - - TPCircularBufferConsume(&p->buffer, bytes_to_copy); - } - else - { - target_buffer->mDataByteSize = 0; - AudioOutputUnitStop(p->audio_unit); - p->is_playing = 0; - } - } - - return noErr; + unsigned int i; + + if (inBusNumber != 0) + { + return noErr; + } + + rdpsndIOSPlugin *p = THIS(inRefCon); + + for (i = 0; i < ioData->mNumberBuffers; i++) + { + AudioBuffer* target_buffer = &ioData->mBuffers[i]; + + int32_t available_bytes = 0; + const void *buffer = TPCircularBufferTail(&p->buffer, &available_bytes); + if (buffer != NULL && available_bytes > 0) + { + const int bytes_to_copy = MIN((int32_t)target_buffer->mDataByteSize, available_bytes); + + memcpy(target_buffer->mData, buffer, bytes_to_copy); + target_buffer->mDataByteSize = bytes_to_copy; + + TPCircularBufferConsume(&p->buffer, bytes_to_copy); + } + else + { + target_buffer->mDataByteSize = 0; + AudioOutputUnitStop(p->audio_unit); + p->is_playing = 0; + } + } + + return noErr; } static BOOL rdpsnd_ios_format_supported(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* format) { - if (format->wFormatTag == WAVE_FORMAT_PCM) - { - return 1; - } - return 0; + if (format->wFormatTag == WAVE_FORMAT_PCM) + { + return 1; + } + return 0; } static void rdpsnd_ios_set_format(rdpsndDevicePlugin* __unused device, AUDIO_FORMAT* __unused format, int __unused latency) @@ -109,170 +108,170 @@ static void rdpsnd_ios_set_volume(rdpsndDevicePlugin* __unused device, UINT32 __ static void rdpsnd_ios_start(rdpsndDevicePlugin* device) { - rdpsndIOSPlugin *p = THIS(device); + rdpsndIOSPlugin *p = THIS(device); - /* If this device is not playing... */ - if (!p->is_playing) - { - /* Start the device. */ - int32_t available_bytes = 0; - TPCircularBufferTail(&p->buffer, &available_bytes); - if (available_bytes > 0) - { - p->is_playing = 1; - AudioOutputUnitStart(p->audio_unit); - } - } + /* If this device is not playing... */ + if (!p->is_playing) + { + /* Start the device. */ + int32_t available_bytes = 0; + TPCircularBufferTail(&p->buffer, &available_bytes); + if (available_bytes > 0) + { + p->is_playing = 1; + AudioOutputUnitStart(p->audio_unit); + } + } } static void rdpsnd_ios_stop(rdpsndDevicePlugin* __unused device) { - rdpsndIOSPlugin *p = THIS(device); + rdpsndIOSPlugin *p = THIS(device); - /* If the device is playing... */ - if (p->is_playing) - { - /* Stop the device. */ - AudioOutputUnitStop(p->audio_unit); - p->is_playing = 0; + /* If the device is playing... */ + if (p->is_playing) + { + /* Stop the device. */ + AudioOutputUnitStop(p->audio_unit); + p->is_playing = 0; - /* Free all buffers. */ - TPCircularBufferClear(&p->buffer); - } + /* Free all buffers. */ + TPCircularBufferClear(&p->buffer); + } } static void rdpsnd_ios_play(rdpsndDevicePlugin* device, BYTE* data, int size) { - rdpsndIOSPlugin *p = THIS(device); - - const BOOL ok = TPCircularBufferProduceBytes(&p->buffer, data, size); - if (!ok) - { - return; - } - - rdpsnd_ios_start(device); + rdpsndIOSPlugin *p = THIS(device); + + const BOOL ok = TPCircularBufferProduceBytes(&p->buffer, data, size); + if (!ok) + { + return; + } + + rdpsnd_ios_start(device); } static void rdpsnd_ios_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int __unused latency) { - rdpsndIOSPlugin *p = THIS(device); - - if (p->is_opened) - { - return; - } + rdpsndIOSPlugin *p = THIS(device); - /* Find the output audio unit. */ - AudioComponentDescription desc; - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_RemoteIO; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - AudioComponent audioComponent = AudioComponentFindNext(NULL, &desc); - if (audioComponent == NULL) return; + if (p->is_opened) + { + return; + } - /* Open the audio unit. */ - OSStatus status = AudioComponentInstanceNew(audioComponent, &p->audio_unit); - if (status != 0) return; + /* Find the output audio unit. */ + AudioComponentDescription desc; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_RemoteIO; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; - /* Set the format for the AudioUnit. */ - AudioStreamBasicDescription audioFormat = {0}; - audioFormat.mSampleRate = format->nSamplesPerSec; - audioFormat.mFormatID = kAudioFormatLinearPCM; - audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; - audioFormat.mFramesPerPacket = 1; /* imminent property of the Linear PCM */ - audioFormat.mChannelsPerFrame = format->nChannels; - audioFormat.mBitsPerChannel = format->wBitsPerSample; - audioFormat.mBytesPerFrame = (format->wBitsPerSample * format->nChannels) / 8; - audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket; - - status = AudioUnitSetProperty( - p->audio_unit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, - 0, - &audioFormat, - sizeof(audioFormat)); - if (status != 0) - { - AudioComponentInstanceDispose(p->audio_unit); - p->audio_unit = NULL; - return; - } - - /* Set up the AudioUnit callback. */ - AURenderCallbackStruct callbackStruct = {0}; - callbackStruct.inputProc = rdpsnd_ios_render_cb; - callbackStruct.inputProcRefCon = p; - status = AudioUnitSetProperty( - p->audio_unit, - kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Input, - 0, - &callbackStruct, - sizeof(callbackStruct)); - if (status != 0) - { - AudioComponentInstanceDispose(p->audio_unit); - p->audio_unit = NULL; - return; - } + AudioComponent audioComponent = AudioComponentFindNext(NULL, &desc); + if (audioComponent == NULL) return; - /* Initialize the AudioUnit. */ - status = AudioUnitInitialize(p->audio_unit); - if (status != 0) - { - AudioComponentInstanceDispose(p->audio_unit); - p->audio_unit = NULL; - return; - } - - /* Allocate the circular buffer. */ - const BOOL ok = TPCircularBufferInit(&p->buffer, CIRCULAR_BUFFER_SIZE); - if (!ok) - { - AudioUnitUninitialize(p->audio_unit); - AudioComponentInstanceDispose(p->audio_unit); - p->audio_unit = NULL; - return; - } + /* Open the audio unit. */ + OSStatus status = AudioComponentInstanceNew(audioComponent, &p->audio_unit); + if (status != 0) return; - p->is_opened = 1; + /* Set the format for the AudioUnit. */ + AudioStreamBasicDescription audioFormat = {0}; + audioFormat.mSampleRate = format->nSamplesPerSec; + audioFormat.mFormatID = kAudioFormatLinearPCM; + audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; + audioFormat.mFramesPerPacket = 1; /* imminent property of the Linear PCM */ + audioFormat.mChannelsPerFrame = format->nChannels; + audioFormat.mBitsPerChannel = format->wBitsPerSample; + audioFormat.mBytesPerFrame = (format->wBitsPerSample * format->nChannels) / 8; + audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket; + + status = AudioUnitSetProperty( + p->audio_unit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &audioFormat, + sizeof(audioFormat)); + if (status != 0) + { + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + /* Set up the AudioUnit callback. */ + AURenderCallbackStruct callbackStruct = {0}; + callbackStruct.inputProc = rdpsnd_ios_render_cb; + callbackStruct.inputProcRefCon = p; + status = AudioUnitSetProperty( + p->audio_unit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &callbackStruct, + sizeof(callbackStruct)); + if (status != 0) + { + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + /* Initialize the AudioUnit. */ + status = AudioUnitInitialize(p->audio_unit); + if (status != 0) + { + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + /* Allocate the circular buffer. */ + const BOOL ok = TPCircularBufferInit(&p->buffer, CIRCULAR_BUFFER_SIZE); + if (!ok) + { + AudioUnitUninitialize(p->audio_unit); + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + return; + } + + p->is_opened = 1; } static void rdpsnd_ios_close(rdpsndDevicePlugin* device) { - rdpsndIOSPlugin *p = THIS(device); + rdpsndIOSPlugin *p = THIS(device); - /* Make sure the device is stopped. */ - rdpsnd_ios_stop(device); + /* Make sure the device is stopped. */ + rdpsnd_ios_stop(device); - /* If the device is open... */ - if (p->is_opened) - { - /* Close the device. */ - AudioUnitUninitialize(p->audio_unit); - AudioComponentInstanceDispose(p->audio_unit); - p->audio_unit = NULL; - p->is_opened = 0; - - /* Destroy the circular buffer. */ - TPCircularBufferCleanup(&p->buffer); - } + /* If the device is open... */ + if (p->is_opened) + { + /* Close the device. */ + AudioUnitUninitialize(p->audio_unit); + AudioComponentInstanceDispose(p->audio_unit); + p->audio_unit = NULL; + p->is_opened = 0; + + /* Destroy the circular buffer. */ + TPCircularBufferCleanup(&p->buffer); + } } static void rdpsnd_ios_free(rdpsndDevicePlugin* device) { - rdpsndIOSPlugin *p = THIS(device); + rdpsndIOSPlugin *p = THIS(device); - /* Ensure the device is closed. */ - rdpsnd_ios_close(device); + /* Ensure the device is closed. */ + rdpsnd_ios_close(device); - /* Free memory associated with the device. */ - free(p); + /* Free memory associated with the device. */ + free(p); } #ifdef STATIC_CHANNELS @@ -281,19 +280,21 @@ static void rdpsnd_ios_free(rdpsndDevicePlugin* device) int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) { - rdpsndIOSPlugin *p = (rdpsndIOSPlugin*)malloc(sizeof(rdpsndIOSPlugin)); - memset(p, 0, sizeof(rdpsndIOSPlugin)); - - p->device.Open = rdpsnd_ios_open; - p->device.FormatSupported = rdpsnd_ios_format_supported; - p->device.SetFormat = rdpsnd_ios_set_format; - p->device.SetVolume = rdpsnd_ios_set_volume; - p->device.Play = rdpsnd_ios_play; - p->device.Start = rdpsnd_ios_start; - p->device.Close = rdpsnd_ios_close; - p->device.Free = rdpsnd_ios_free; - - pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p); - - return 0; -} \ No newline at end of file + rdpsndIOSPlugin* p = (rdpsndIOSPlugin*) calloc(1, sizeof(rdpsndIOSPlugin)); + + if (!p) + return -1; + + p->device.Open = rdpsnd_ios_open; + p->device.FormatSupported = rdpsnd_ios_format_supported; + p->device.SetFormat = rdpsnd_ios_set_format; + p->device.SetVolume = rdpsnd_ios_set_volume; + p->device.Play = rdpsnd_ios_play; + p->device.Start = rdpsnd_ios_start; + p->device.Close = rdpsnd_ios_close; + p->device.Free = rdpsnd_ios_free; + + pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)p); + + return 0; +} diff --git a/channels/rdpsnd/client/mac/rdpsnd_mac.c b/channels/rdpsnd/client/mac/rdpsnd_mac.c index 1fe05242c..96ffacd89 100644 --- a/channels/rdpsnd/client/mac/rdpsnd_mac.c +++ b/channels/rdpsnd/client/mac/rdpsnd_mac.c @@ -29,7 +29,6 @@ #include #include -#include #include #include @@ -282,23 +281,21 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE { rdpsndMacPlugin* mac; - mac = (rdpsndMacPlugin*) malloc(sizeof(rdpsndMacPlugin)); + mac = (rdpsndMacPlugin*) calloc(1, sizeof(rdpsndMacPlugin)); - if (mac) - { - ZeroMemory(mac, sizeof(rdpsndMacPlugin)); + if (!mac) + return -1; - mac->device.Open = rdpsnd_mac_open; - mac->device.FormatSupported = rdpsnd_mac_format_supported; - mac->device.SetFormat = rdpsnd_mac_set_format; - mac->device.SetVolume = rdpsnd_mac_set_volume; - mac->device.Play = rdpsnd_mac_play; - mac->device.Start = rdpsnd_mac_start; - mac->device.Close = rdpsnd_mac_close; - mac->device.Free = rdpsnd_mac_free; + mac->device.Open = rdpsnd_mac_open; + mac->device.FormatSupported = rdpsnd_mac_format_supported; + mac->device.SetFormat = rdpsnd_mac_set_format; + mac->device.SetVolume = rdpsnd_mac_set_volume; + mac->device.Play = rdpsnd_mac_play; + mac->device.Start = rdpsnd_mac_start; + mac->device.Close = rdpsnd_mac_close; + mac->device.Free = rdpsnd_mac_free; - pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) mac); - } + pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) mac); return 0; } diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c index e20cce9be..912563fe9 100644 --- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c @@ -37,7 +37,6 @@ #include #include -#include #include "rdpsnd_main.h" @@ -74,18 +73,15 @@ static void rdpsnd_pulse_context_state_callback(pa_context* context, void* userd switch (state) { case PA_CONTEXT_READY: - DEBUG_SVC("PA_CONTEXT_READY"); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; case PA_CONTEXT_FAILED: case PA_CONTEXT_TERMINATED: - DEBUG_SVC("PA_CONTEXT_FAILED/PA_CONTEXT_TERMINATED %d", (int)state); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; default: - DEBUG_SVC("state %d", (int)state); break; } } @@ -100,7 +96,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device) if (pa_context_connect(pulse->context, NULL, 0, NULL)) { - DEBUG_WARN("pa_context_connect failed (%d)", pa_context_errno(pulse->context)); return FALSE; } @@ -109,7 +104,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device) if (pa_threaded_mainloop_start(pulse->mainloop) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); - DEBUG_WARN("pa_threaded_mainloop_start failed (%d)", pa_context_errno(pulse->context)); return FALSE; } @@ -122,7 +116,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device) if (!PA_CONTEXT_IS_GOOD(state)) { - DEBUG_WARN("bad context state (%d)", pa_context_errno(pulse->context)); break; } @@ -133,7 +126,6 @@ static BOOL rdpsnd_pulse_connect(rdpsndDevicePlugin* device) if (state == PA_CONTEXT_READY) { - DEBUG_SVC("connected"); return TRUE; } else @@ -173,18 +165,15 @@ static void rdpsnd_pulse_stream_state_callback(pa_stream* stream, void* userdata switch (state) { case PA_STREAM_READY: - DEBUG_SVC("PA_STREAM_READY"); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; case PA_STREAM_FAILED: case PA_STREAM_TERMINATED: - DEBUG_SVC("state %d", (int)state); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; default: - DEBUG_SVC("state %d", (int)state); break; } } @@ -270,7 +259,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, if (!pulse->context || pulse->stream) { - DEBUG_WARN("pulse stream has been created."); return; } @@ -280,7 +268,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, if (pa_sample_spec_valid(&pulse->sample_spec) == 0) { pa_sample_spec_snprint(ss, sizeof(ss), &pulse->sample_spec); - DEBUG_WARN("Invalid sample spec %s", ss); return; } @@ -291,7 +278,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, if (!pulse->stream) { pa_threaded_mainloop_unlock(pulse->mainloop); - DEBUG_WARN("pa_stream_new failed (%d)", pa_context_errno(pulse->context)); return; } @@ -315,8 +301,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, pulse->device_name, pulse->latency > 0 ? &buffer_attr : NULL, flags, NULL, NULL) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); - DEBUG_WARN("pa_stream_connect_playback failed (%d)", - pa_context_errno(pulse->context)); return; } @@ -329,8 +313,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, if (!PA_STREAM_IS_GOOD(state)) { - DEBUG_WARN("bad stream state (%d)", - pa_context_errno(pulse->context)); break; } @@ -349,8 +331,6 @@ static void rdpsnd_pulse_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, pulse->gsm_context = gsm_create(); #endif - - DEBUG_SVC("connected"); } else { @@ -584,8 +564,6 @@ static void rdpsnd_pulse_play(rdpsndDevicePlugin* device, BYTE* data, int size) if (status < 0) { - DEBUG_WARN("pa_stream_write failed (%d)", - pa_context_errno(pulse->context)); break; } @@ -653,8 +631,10 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE ADDIN_ARGV* args; rdpsndPulsePlugin* pulse; - pulse = (rdpsndPulsePlugin*) malloc(sizeof(rdpsndPulsePlugin)); - ZeroMemory(pulse, sizeof(rdpsndPulsePlugin)); + pulse = (rdpsndPulsePlugin*) calloc(1, sizeof(rdpsndPulsePlugin)); + + if (!pulse) + return -1; pulse->device.Open = rdpsnd_pulse_open; pulse->device.FormatSupported = rdpsnd_pulse_format_supported; @@ -678,7 +658,6 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE if (!pulse->mainloop) { - DEBUG_WARN("pa_threaded_mainloop_new failed"); rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse); return 1; } @@ -687,7 +666,6 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE if (!pulse->context) { - DEBUG_WARN("pa_context_new failed"); rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse); return 1; } @@ -696,7 +674,6 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE if (!rdpsnd_pulse_connect((rdpsndDevicePlugin*)pulse)) { - DEBUG_WARN("rdpsnd_pulse_connect failed"); rdpsnd_pulse_free((rdpsndDevicePlugin*)pulse); return 1; } diff --git a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c index 7c1e47cd0..961b95e83 100644 --- a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c +++ b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c @@ -34,7 +34,6 @@ #include #include -#include #include "rdpsnd_main.h" @@ -333,8 +332,10 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE ADDIN_ARGV* args; rdpsndWinmmPlugin* winmm; - winmm = (rdpsndWinmmPlugin*) malloc(sizeof(rdpsndWinmmPlugin)); - ZeroMemory(winmm, sizeof(rdpsndWinmmPlugin)); + winmm = (rdpsndWinmmPlugin*) calloc(1, sizeof(rdpsndWinmmPlugin)); + + if (!winmm) + return -1; winmm->device.DisableConfirmThread = TRUE; diff --git a/channels/sample/CMakeLists.txt b/channels/sample/CMakeLists.txt deleted file mode 100644 index 183b8a65f..000000000 --- a/channels/sample/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -# 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("sample") - -if(WITH_CLIENT_CHANNELS) - add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME}) -endif() - diff --git a/channels/sample/ChannelOptions.cmake b/channels/sample/ChannelOptions.cmake deleted file mode 100644 index ae977457d..000000000 --- a/channels/sample/ChannelOptions.cmake +++ /dev/null @@ -1,16 +0,0 @@ -set(OPTION_DEFAULT OFF) - -if(WITH_SAMPLE) - set(OPTION_CLIENT_DEFAULT ON) -else() - set(OPTION_CLIENT_DEFAULT OFF) -endif() -set(OPTION_SERVER_DEFAULT OFF) - -define_channel_options(NAME "sample" TYPE "static" - DESCRIPTION "Sample Virtual Channel Extension" - SPECIFICATIONS "" - DEFAULT ${OPTION_DEFAULT}) - -define_channel_client_options(${OPTION_CLIENT_DEFAULT}) -define_channel_server_options(${OPTION_SERVER_DEFAULT}) diff --git a/channels/sample/client/CMakeLists.txt b/channels/sample/client/CMakeLists.txt deleted file mode 100644 index 867406d63..000000000 --- a/channels/sample/client/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -# 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_client("sample") - -set(${MODULE_PREFIX}_SRCS - sample_main.c - sample_main.h) - -add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry") - -set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "") - -set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS - MONOLITHIC ${MONOLITHIC_BUILD} - MODULE freerdp - MODULES freerdp-utils) - -install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets) - -set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client") diff --git a/channels/sample/client/readme.txt b/channels/sample/client/readme.txt deleted file mode 100644 index 34c1b340c..000000000 --- a/channels/sample/client/readme.txt +++ /dev/null @@ -1,11 +0,0 @@ - -This is a skeleton virtual channel plugin for freerdp -To create your own virtual channel plugin, copy this directory -then change all references of "skel" to your plugin name -remember, plugin name are 7 chars or less, no spaces or funny chars - -server_chan_test.cpp is an example of how to open a channel to the client -this code needs to be compiled and run on the server in an rdp session -when connect with a client that has the "skel" plugin loaded - -Jay diff --git a/channels/sample/client/sample_main.c b/channels/sample/client/sample_main.c deleted file mode 100644 index 3326b7168..000000000 --- a/channels/sample/client/sample_main.c +++ /dev/null @@ -1,143 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Sample Virtual Channel - * - * Copyright 2009-2012 Jay Sorg - * Copyright 2010-2012 Vic Lee - * - * 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 - -#ifndef _WIN32 -#include -#endif - -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "sample_main.h" - -struct sample_plugin -{ - rdpSvcPlugin plugin; - - /* put your private data here */ -}; - -static void sample_process_receive(rdpSvcPlugin* plugin, wStream* data_in) -{ - int bytes; - wStream* data_out; - samplePlugin* sample = (samplePlugin*) plugin; - - fprintf(stderr, "sample_process_receive:\n"); - - if (!sample) - { - fprintf(stderr, "sample_process_receive: sample is nil\n"); - return; - } - - /* process data in (from server) here */ - /* here we just send the same data back */ - - bytes = Stream_Capacity(data_in); - fprintf(stderr, "sample_process_receive: got bytes %d\n", bytes); - - if (bytes > 0) - { - data_out = Stream_New(NULL, bytes); - Stream_Copy(data_out, data_in, bytes); - /* svc_plugin_send takes ownership of data_out, that is why - we do not free it */ - - bytes = Stream_GetPosition(data_in); - fprintf(stderr, "sample_process_receive: sending bytes %d\n", bytes); - - svc_plugin_send(plugin, data_out); - } - - Stream_Free(data_in, TRUE); -} - -static void sample_process_connect(rdpSvcPlugin* plugin) -{ - samplePlugin* sample = (samplePlugin*) plugin; - DEBUG_SVC("connecting"); - - fprintf(stderr, "sample_process_connect:\n"); - - if (!sample) - return; -} - -static void sample_process_event(rdpSvcPlugin* plugin, wMessage* event) -{ - fprintf(stderr, "sample_process_event:\n"); - - /* events coming from main freerdp window to plugin */ - /* send them back with svc_plugin_send_event */ - - freerdp_event_free(event); -} - -static void sample_process_terminate(rdpSvcPlugin* plugin) -{ - samplePlugin* sample = (samplePlugin*) plugin; - - fprintf(stderr, "sample_process_terminate:\n"); - - if (!sample) - return; - - /* put your cleanup here */ - - free(plugin); -} - -#define VirtualChannelEntry sample_VirtualChannelEntry - -int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) -{ - samplePlugin* _p; - - _p = (samplePlugin*) malloc(sizeof(samplePlugin)); - ZeroMemory(_p, sizeof(samplePlugin)); - - _p->plugin.channel_def.options = - CHANNEL_OPTION_INITIALIZED | - CHANNEL_OPTION_ENCRYPT_RDP; - - strcpy(_p->plugin.channel_def.name, "sample"); - - _p->plugin.connect_callback = sample_process_connect; - _p->plugin.receive_callback = sample_process_receive; - _p->plugin.event_callback = sample_process_event; - _p->plugin.terminate_callback = sample_process_terminate; - - svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints); - - return 1; -} diff --git a/channels/sample/client/server_chan_test.cpp b/channels/sample/client/server_chan_test.cpp deleted file mode 100644 index 577d7b1d1..000000000 --- a/channels/sample/client/server_chan_test.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// xrdp_chan_test.cpp : Basic test for virtual channel use. - -// These headers are required for the windows terminal service calls. -#include "windows.h" -#include "wtsapi32.h" -#include - -#define DSIZE 1024 - -int main() -{ - // Initialize the data for send/receive - char* data; - char* data1; - data = (char*)malloc(DSIZE); - data1 = (char*)malloc(DSIZE); - memset(data, 0xca, DSIZE); - memset(data1, 0, DSIZE); - - // Open the skel channel in current session - void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, "skel", 0); - - unsigned long written = 0; - // Write the data to the channel - bool ret = WTSVirtualChannelWrite(channel, data, DSIZE, &written); - if (!ret) - { - long err = GetLastError(); - fprintf(stderr, "error 0x%8.8x\n", err); - return 1; - } - - ret = WTSVirtualChannelRead(channel, 100, data1, DSIZE, &written); - if (!ret) - { - long err = GetLastError(); - fprintf(stderr, "error 0x%8.8x\n", err); - return 1; - } - if (written != DSIZE) - { - fprintf(stderr, "error read %d\n", written); - return 1; - } - - ret = WTSVirtualChannelClose(channel); - if (memcmp(data, data1, DSIZE) == 0) - { - } - else - { - fprintf(stderr, "error data no match\n"); - return 1; - } - - fprintf(stderr, "Success!\n"); - - Sleep(2000); - return 0; -} diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index 2143f6c76..de78217bd 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -53,7 +53,6 @@ #include #include -#include typedef struct _SERIAL_DEVICE SERIAL_DEVICE; @@ -100,13 +99,10 @@ static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) { irp->IoStatus = STATUS_UNSUCCESSFUL; FileId = 0; - - DEBUG_WARN("failed to create %s", path); } else { serial->tty = tty; - DEBUG_SVC("%s(%d) created.", serial->path, FileId); } Stream_Write_UINT32(irp->output, FileId); /* FileId (4 bytes) */ @@ -126,12 +122,9 @@ static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp) if (!tty) { irp->IoStatus = STATUS_UNSUCCESSFUL; - DEBUG_WARN("tty not valid."); } else { - DEBUG_SVC("%s(%d) closed.", serial->path, tty->id); - serial_tty_free(tty); serial->tty = NULL; } @@ -156,8 +149,6 @@ static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; - - DEBUG_WARN("tty not valid."); } else { @@ -169,12 +160,10 @@ static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) free(buffer); buffer = NULL; Length = 0; - - DEBUG_WARN("read %s(%d) failed.", serial->path, tty->id); } else { - DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, tty->id); + } } @@ -207,8 +196,6 @@ static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp) irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; - DEBUG_WARN("tty not valid."); - Stream_Write_UINT32(irp->output, Length); /* Length (4 bytes) */ Stream_Write_UINT8(irp->output, 0); /* Padding (1 byte) */ irp->Complete(irp); @@ -252,8 +239,6 @@ static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp) { irp->IoStatus = STATUS_UNSUCCESSFUL; OutputBufferLength = 0; - - DEBUG_WARN("tty not valid."); } else { @@ -291,7 +276,6 @@ static void serial_process_irp(SERIAL_DEVICE* serial, IRP* irp) break; default: - DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; diff --git a/channels/serial/client/serial_tty.c b/channels/serial/client/serial_tty.c index 44faca061..9e65a71ef 100644 --- a/channels/serial/client/serial_tty.c +++ b/channels/serial/client/serial_tty.c @@ -30,7 +30,6 @@ #include #include -#include #include #ifndef _WIN32 @@ -119,19 +118,16 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, case IOCTL_SERIAL_SET_BAUD_RATE: Stream_Read_UINT32(input, tty->baud_rate); tty_set_termios(tty); - DEBUG_SVC("SERIAL_SET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_GET_BAUD_RATE: OutputBufferLength = 4; Stream_Write_UINT32(output, tty->baud_rate); - DEBUG_SVC("SERIAL_GET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_SET_QUEUE_SIZE: Stream_Read_UINT32(input, tty->queue_in_size); Stream_Read_UINT32(input, tty->queue_out_size); - DEBUG_SVC("SERIAL_SET_QUEUE_SIZE in %d out %d", tty->queue_in_size, tty->queue_out_size); break; case IOCTL_SERIAL_SET_LINE_CONTROL: @@ -139,12 +135,9 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, Stream_Read_UINT8(input, tty->parity); Stream_Read_UINT8(input, tty->word_length); tty_set_termios(tty); - DEBUG_SVC("SERIAL_SET_LINE_CONTROL stop %d parity %d word %d", - tty->stop_bits, tty->parity, tty->word_length); break; case IOCTL_SERIAL_GET_LINE_CONTROL: - DEBUG_SVC("SERIAL_GET_LINE_CONTROL"); OutputBufferLength = 3; Stream_Write_UINT8(output, tty->stop_bits); Stream_Write_UINT8(output, tty->parity); @@ -152,25 +145,21 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_IMMEDIATE_CHAR: - DEBUG_SVC("SERIAL_IMMEDIATE_CHAR"); Stream_Read_UINT8(input, immediate); tty_write_data(tty, &immediate, 1); break; case IOCTL_SERIAL_CONFIG_SIZE: - DEBUG_SVC("SERIAL_CONFIG_SIZE"); OutputBufferLength = 4; Stream_Write_UINT32(output, 0); break; case IOCTL_SERIAL_GET_CHARS: - DEBUG_SVC("SERIAL_GET_CHARS"); OutputBufferLength = 6; Stream_Write(output, tty->chars, 6); break; case IOCTL_SERIAL_SET_CHARS: - DEBUG_SVC("SERIAL_SET_CHARS"); Stream_Read(input, tty->chars, 6); tty_set_termios(tty); break; @@ -182,8 +171,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, Stream_Write_UINT32(output, tty->xonoff); Stream_Write_UINT32(output, tty->onlimit); Stream_Write_UINT32(output, tty->offlimit); - DEBUG_SVC("IOCTL_SERIAL_GET_HANDFLOW %X %X %X %X", - tty->control, tty->xonoff, tty->onlimit, tty->offlimit); break; case IOCTL_SERIAL_SET_HANDFLOW: @@ -191,8 +178,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, Stream_Read_UINT32(input, tty->xonoff); Stream_Read_UINT32(input, tty->onlimit); Stream_Read_UINT32(input, tty->offlimit); - DEBUG_SVC("IOCTL_SERIAL_SET_HANDFLOW %X %X %X %X", - tty->control, tty->xonoff, tty->onlimit, tty->offlimit); tty_set_termios(tty); break; @@ -211,17 +196,9 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, tty->read_total_timeout_multiplier = 0; } - DEBUG_SVC("SERIAL_SET_TIMEOUTS read timeout %d %d %d", - tty->read_interval_timeout, - tty->read_total_timeout_multiplier, - tty->read_total_timeout_constant); break; case IOCTL_SERIAL_GET_TIMEOUTS: - DEBUG_SVC("SERIAL_GET_TIMEOUTS read timeout %d %d %d", - tty->read_interval_timeout, - tty->read_total_timeout_multiplier, - tty->read_total_timeout_constant); OutputBufferLength = 20; Stream_Write_UINT32(output, tty->read_interval_timeout); Stream_Write_UINT32(output, tty->read_total_timeout_multiplier); @@ -231,18 +208,15 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_GET_WAIT_MASK: - DEBUG_SVC("SERIAL_GET_WAIT_MASK %X", tty->wait_mask); OutputBufferLength = 4; Stream_Write_UINT32(output, tty->wait_mask); break; case IOCTL_SERIAL_SET_WAIT_MASK: Stream_Read_UINT32(input, tty->wait_mask); - DEBUG_SVC("SERIAL_SET_WAIT_MASK %X", tty->wait_mask); break; case IOCTL_SERIAL_SET_DTR: - DEBUG_SVC("SERIAL_SET_DTR"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); @@ -250,7 +224,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_CLR_DTR: - DEBUG_SVC("SERIAL_CLR_DTR"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); @@ -258,7 +231,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_SET_RTS: - DEBUG_SVC("SERIAL_SET_RTS"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); @@ -266,7 +238,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_CLR_RTS: - DEBUG_SVC("SERIAL_CLR_RTS"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); @@ -290,7 +261,6 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, if (result & TIOCM_RTS) modemstate |= SERIAL_MS_RTS; #endif - DEBUG_SVC("SERIAL_GET_MODEMSTATUS %X", modemstate); OutputBufferLength = 4; Stream_Write_UINT32(output, modemstate); break; @@ -305,23 +275,18 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, ioctl(tty->fd, TIOCINQ, &result); #endif Stream_Write_UINT32(output, result); /* Amount in in queue */ - if (result) - DEBUG_SVC("SERIAL_GET_COMMSTATUS in queue %d", result); result = 0; #ifdef TIOCOUTQ ioctl(tty->fd, TIOCOUTQ, &result); #endif Stream_Write_UINT32(output, result); /* Amount in out queue */ - DEBUG_SVC("SERIAL_GET_COMMSTATUS out queue %d", result); - Stream_Write_UINT8(output, 0); /* EofReceived */ Stream_Write_UINT8(output, 0); /* WaitForImmediate */ break; case IOCTL_SERIAL_PURGE: Stream_Read_UINT32(input, purge_mask); - DEBUG_SVC("SERIAL_PURGE purge_mask %X", purge_mask); /* See http://msdn.microsoft.com/en-us/library/ms901431.aspx PURGE_TXCLEAR Clears the output buffer, if the driver has one. @@ -330,25 +295,16 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, It clearly states to clear the *driver* buffer, not the port buffer */ -#ifdef DEBUG_SVC - if (purge_mask & SERIAL_PURGE_TXCLEAR) - DEBUG_SVC("Ignoring SERIAL_PURGE_TXCLEAR"); - if (purge_mask & SERIAL_PURGE_RXCLEAR) - DEBUG_SVC("Ignoring SERIAL_PURGE_RXCLEAR"); -#endif - if (purge_mask & SERIAL_PURGE_TXABORT) *abortIo |= SERIAL_ABORT_IO_WRITE; if (purge_mask & SERIAL_PURGE_RXABORT) *abortIo |= SERIAL_ABORT_IO_READ; break; case IOCTL_SERIAL_WAIT_ON_MASK: - DEBUG_SVC("SERIAL_WAIT_ON_MASK %X", tty->wait_mask); tty->event_pending = 1; OutputBufferLength = 4; if (serial_tty_get_event(tty, &result)) { - DEBUG_SVC("WAIT end event = %X", result); Stream_Write_UINT32(output, result); break; } @@ -356,29 +312,23 @@ UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, break; case IOCTL_SERIAL_SET_BREAK_ON: - DEBUG_SVC("SERIAL_SET_BREAK_ON"); tcsendbreak(tty->fd, 0); break; case IOCTL_SERIAL_RESET_DEVICE: - DEBUG_SVC("SERIAL_RESET_DEVICE"); break; case IOCTL_SERIAL_SET_BREAK_OFF: - DEBUG_SVC("SERIAL_SET_BREAK_OFF"); break; case IOCTL_SERIAL_SET_XOFF: - DEBUG_SVC("SERIAL_SET_XOFF"); break; case IOCTL_SERIAL_SET_XON: - DEBUG_SVC("SERIAL_SET_XON"); tcflow(tty->fd, TCION); break; default: - DEBUG_SVC("NOT FOUND IoControlCode SERIAL IOCTL 0x%08X", IoControlCode); return STATUS_INVALID_PARAMETER; } @@ -457,11 +407,7 @@ BOOL serial_tty_read(SERIAL_TTY* tty, BYTE* buffer, UINT32* Length) status = read(tty->fd, buffer, *Length); if (status < 0) - { - DEBUG_WARN("failed with %zd, errno=[%d] %s\n", - status, errno, strerror(errno)); return FALSE; - } tty->event_txempty = status; *Length = status; @@ -535,13 +481,12 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id) if (tty->fd < 0) { perror("open"); - DEBUG_WARN("failed to open device %s", path); serial_tty_free(tty); return NULL; } else { - DEBUG_SVC("tty fd %d successfully opened", tty->fd); + } tty->ptermios = (struct termios*) calloc(1, sizeof(struct termios)); @@ -563,7 +508,6 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id) if (!tty_get_termios(tty)) { - DEBUG_WARN("%s access denied", path); fflush(stdout); serial_tty_free(tty); return NULL; @@ -589,7 +533,6 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id) /* all read and writes should be non-blocking */ if (fcntl(tty->fd, F_SETFL, O_NONBLOCK) == -1) { - DEBUG_WARN("%s fcntl", path); perror("fcntl"); serial_tty_free(tty) ; return NULL; @@ -620,15 +563,12 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result) if (bytes > 0) { - DEBUG_SVC("bytes %d", bytes); - if (bytes > tty->event_rlsd) { tty->event_rlsd = bytes; if (tty->wait_mask & SERIAL_EV_RLSD) { - DEBUG_SVC("SERIAL_EV_RLSD"); *result |= SERIAL_EV_RLSD; status = TRUE; } @@ -636,14 +576,12 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result) if ((bytes > 1) && (tty->wait_mask & SERIAL_EV_RXFLAG)) { - DEBUG_SVC("SERIAL_EV_RXFLAG bytes %d", bytes); *result |= SERIAL_EV_RXFLAG; status = TRUE; } if ((tty->wait_mask & SERIAL_EV_RXCHAR)) { - DEBUG_SVC("SERIAL_EV_RXCHAR bytes %d", bytes); *result |= SERIAL_EV_RXCHAR; status = TRUE; } @@ -658,7 +596,6 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result) ioctl(tty->fd, TIOCOUTQ, &bytes); if ((bytes == 0) && (tty->event_txempty > 0) && (tty->wait_mask & SERIAL_EV_TXEMPTY)) { - DEBUG_SVC("SERIAL_EV_TXEMPTY"); *result |= SERIAL_EV_TXEMPTY; status = TRUE; } @@ -669,9 +606,9 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result) if ((bytes & TIOCM_DSR) != tty->event_dsr) { tty->event_dsr = bytes & TIOCM_DSR; + if (tty->wait_mask & SERIAL_EV_DSR) { - DEBUG_SVC("SERIAL_EV_DSR %s", (bytes & TIOCM_DSR) ? "ON" : "OFF"); *result |= SERIAL_EV_DSR; status = TRUE; } @@ -680,9 +617,9 @@ BOOL serial_tty_get_event(SERIAL_TTY* tty, UINT32* result) if ((bytes & TIOCM_CTS) != tty->event_cts) { tty->event_cts = bytes & TIOCM_CTS; + if (tty->wait_mask & SERIAL_EV_CTS) { - DEBUG_SVC("SERIAL_EV_CTS %s", (bytes & TIOCM_CTS) ? "ON" : "OFF"); *result |= SERIAL_EV_CTS; status = TRUE; } @@ -700,8 +637,6 @@ static BOOL tty_get_termios(SERIAL_TTY* tty) struct termios* ptermios; ptermios = tty->ptermios; - DEBUG_SVC("tcgetattr? %d", tcgetattr(tty->fd, ptermios) >= 0); - if (tcgetattr(tty->fd, ptermios) < 0) return FALSE; diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c index ec1ee44c3..ec0426fba 100644 --- a/channels/tsmf/client/tsmf_main.c +++ b/channels/tsmf/client/tsmf_main.c @@ -114,9 +114,7 @@ BOOL tsmf_push_event(IWTSVirtualChannelCallback *pChannelCallback, wMessage *eve return TRUE; } -static int tsmf_on_data_received(IWTSVirtualChannelCallback *pChannelCallback, - UINT32 cbSize, - BYTE *pBuffer) +static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { int length; wStream *input; @@ -126,14 +124,17 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback *pChannelCallback, UINT32 MessageId; UINT32 FunctionId; UINT32 InterfaceId; - TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback; + TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback; + UINT32 cbSize = Stream_GetRemainingLength(data); + /* 2.2.1 Shared Message Header (SHARED_MSG_HEADER) */ if(cbSize < 12) { DEBUG_WARN("invalid size. cbSize=%d", cbSize); return 1; } - input = Stream_New((BYTE *) pBuffer, cbSize); + + input = data; output = Stream_New(NULL, 256); Stream_Seek(output, 8); Stream_Read_UINT32(input, InterfaceId); @@ -250,7 +251,7 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback *pChannelCallback, default: break; } - Stream_Free(input, FALSE); + input = NULL; ifman.input = NULL; if(status == -1) diff --git a/client/Android/FreeRDPCore/jni/android_jni_utils.c b/client/Android/FreeRDPCore/jni/android_jni_utils.c index 4e6357b3a..f83f74938 100644 --- a/client/Android/FreeRDPCore/jni/android_jni_utils.c +++ b/client/Android/FreeRDPCore/jni/android_jni_utils.c @@ -203,8 +203,6 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) result = init_callback_environment(vm); setlocale(LC_ALL, ""); - - freerdp_channels_global_init(); return result; } diff --git a/client/DirectFB/dfreerdp.c b/client/DirectFB/dfreerdp.c index cc621480b..df68a1d6c 100644 --- a/client/DirectFB/dfreerdp.c +++ b/client/DirectFB/dfreerdp.c @@ -441,8 +441,6 @@ int main(int argc, char* argv[]) setlocale(LC_ALL, ""); - freerdp_channels_global_init(); - g_sem = CreateSemaphore(NULL, 0, 1, NULL); instance = freerdp_new(); @@ -484,7 +482,5 @@ int main(int argc, char* argv[]) WaitForSingleObject(g_sem, INFINITE); } - freerdp_channels_global_uninit(); - return 0; } diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index fda9a8dcc..5de0da47f 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -760,8 +760,6 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type) return; gdi_free(context->instance); - - freerdp_channels_global_uninit(); if (pixel_data) free(pixel_data); diff --git a/client/Mac/mf_client.m b/client/Mac/mf_client.m index b9b16171f..9b22e94c8 100755 --- a/client/Mac/mf_client.m +++ b/client/Mac/mf_client.m @@ -33,12 +33,11 @@ void mfreerdp_client_global_init() { freerdp_handle_signals(); - freerdp_channels_global_init(); } void mfreerdp_client_global_uninit() { - freerdp_channels_global_uninit(); + } int mfreerdp_client_start(rdpContext* context) diff --git a/client/Sample/freerdp.c b/client/Sample/freerdp.c index 065cada69..4495bf9a9 100644 --- a/client/Sample/freerdp.c +++ b/client/Sample/freerdp.c @@ -305,8 +305,6 @@ int main(int argc, char* argv[]) rdpChannels* channels; struct thread_data* data; - freerdp_channels_global_init(); - g_sem = CreateSemaphore(NULL, 0, 1, NULL); instance = freerdp_new(); @@ -341,7 +339,5 @@ int main(int argc, char* argv[]) WaitForSingleObject(g_sem, INFINITE); } - freerdp_channels_global_uninit(); - return 0; } diff --git a/client/Windows/cli/wfreerdp.c b/client/Windows/cli/wfreerdp.c index f19cc7ecc..c5f5fa0a8 100644 --- a/client/Windows/cli/wfreerdp.c +++ b/client/Windows/cli/wfreerdp.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c index 7efbac346..ec7c70db2 100644 --- a/client/Windows/wf_interface.c +++ b/client/Windows/wf_interface.c @@ -43,9 +43,7 @@ #include #include #include -#include -//#include #include #include #include @@ -1171,8 +1169,6 @@ void wfreerdp_client_global_init(void) wf_create_console(); #endif - freerdp_channels_global_init(); - freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); } diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt index 6cbe43a42..6c004e678 100644 --- a/client/X11/CMakeLists.txt +++ b/client/X11/CMakeLists.txt @@ -26,6 +26,8 @@ include_directories(${OPENSSL_INCLUDE_DIR}) set(${MODULE_PREFIX}_SRCS xf_gdi.c xf_gdi.h + xf_gfx.c + xf_gfx.h xf_rail.c xf_rail.h xf_tsmf.c diff --git a/client/X11/generate_argument_docbook.c b/client/X11/generate_argument_docbook.c index aaab2239c..4b49f34da 100644 --- a/client/X11/generate_argument_docbook.c +++ b/client/X11/generate_argument_docbook.c @@ -154,9 +154,9 @@ int main(int argc, char *argv[]) fprintf(fp, "\t\t\t\t\t%s\n", format); fprintf(fp, "\t\t\t\t\n"); fprintf(fp, "\t\t\t\n"); - free(name); - free(format); - free(text); + free((void*) name); + free((void*) format); + free((void*) text); } fprintf(fp, "\t\t\n"); fprintf(fp, "\t\n"); diff --git a/client/X11/xf_channels.c b/client/X11/xf_channels.c index 24325046e..9bb36152e 100644 --- a/client/X11/xf_channels.c +++ b/client/X11/xf_channels.c @@ -26,6 +26,8 @@ #include "xf_client.h" #include "xfreerdp.h" +#include "xf_gfx.h" + void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e) { xfContext* xfc = (xfContext*) context; @@ -34,9 +36,22 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven { xfc->rdpei = (RdpeiClientContext*) e->pInterface; } + else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) + { + xf_graphics_pipeline_init(xfc, (RdpgfxClientContext*) e->pInterface); + } } void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e) { + xfContext* xfc = (xfContext*) context; + if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) + { + xfc->rdpei = NULL; + } + else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) + { + xf_graphics_pipeline_uninit(xfc, (RdpgfxClientContext*) e->pInterface); + } } diff --git a/client/X11/xf_channels.h b/client/X11/xf_channels.h index bb52d5e52..dd5969d62 100644 --- a/client/X11/xf_channels.h +++ b/client/X11/xf_channels.h @@ -23,6 +23,7 @@ #include #include #include +#include int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface); int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface); diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 26a4bb5be..8011e6a82 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -762,16 +762,18 @@ BOOL xf_post_connect(freerdp *instance) rdpChannels *channels; rdpSettings *settings; ResizeWindowEventArgs e; - RFX_CONTEXT *rfx_context = NULL; - NSC_CONTEXT *nsc_context = NULL; - xfContext *xfc = (xfContext *) instance->context; + xfContext* xfc = (xfContext*) instance->context; + cache = instance->context->cache; channels = instance->context->channels; settings = instance->settings; - if(!xf_get_pixmap_info(xfc)) + + if (!xf_get_pixmap_info(xfc)) return FALSE; + xf_register_graphics(instance->context->graphics); - if(xfc->settings->SoftwareGdi) + + if (xfc->settings->SoftwareGdi) { rdpGdi *gdi; UINT32 flags; @@ -783,24 +785,26 @@ BOOL xf_post_connect(freerdp *instance) gdi_init(instance, flags, NULL); gdi = instance->context->gdi; xfc->primary_buffer = gdi->primary_buffer; - rfx_context = gdi->rfx_context; + + xfc->rfx = gdi->rfx_context; } else { xfc->srcBpp = instance->settings->ColorDepth; xf_gdi_register_update_callbacks(instance->update); xfc->hdc = gdi_CreateDC(xfc->clrconv, xfc->bpp); - if(instance->settings->RemoteFxCodec) + + if (instance->settings->RemoteFxCodec) { - rfx_context = (void *) rfx_context_new(FALSE); - xfc->rfx_context = rfx_context; + xfc->rfx = rfx_context_new(FALSE); } - if(instance->settings->NSCodec) + + if (instance->settings->NSCodec) { - nsc_context = (void *) nsc_context_new(); - xfc->nsc_context = nsc_context; + xfc->nsc = nsc_context_new(); } } + xfc->originalWidth = settings->DesktopWidth; xfc->originalHeight = settings->DesktopHeight; xfc->currentWidth = xfc->originalWidth; @@ -810,12 +814,17 @@ BOOL xf_post_connect(freerdp *instance) xfc->offset_y = 0; xfc->width = settings->DesktopWidth; xfc->height = settings->DesktopHeight; - if(settings->RemoteApplicationMode) + + if (settings->RemoteApplicationMode) xfc->remote_app = TRUE; + xf_create_window(xfc); + ZeroMemory(&gcv, sizeof(gcv)); + if(xfc->modifierMap) XFreeModifiermap(xfc->modifierMap); + xfc->modifierMap = XGetModifierMapping(xfc->display); xfc->gc = XCreateGC(xfc->display, xfc->drawable, GCGraphicsExposures, &gcv); xfc->primary = XCreatePixmap(xfc->display, xfc->drawable, xfc->width, xfc->height, xfc->depth); @@ -830,7 +839,8 @@ BOOL xf_post_connect(freerdp *instance) xfc->image = XCreateImage(xfc->display, xfc->visual, xfc->depth, ZPixmap, 0, (char *) xfc->primary_buffer, xfc->width, xfc->height, xfc->scanline_pad, 0); xfc->bmp_codec_none = (BYTE *) malloc(64 * 64 * 4); - if(xfc->settings->SoftwareGdi) + + if (xfc->settings->SoftwareGdi) { instance->update->BeginPaint = xf_sw_begin_paint; instance->update->EndPaint = xf_sw_end_paint; @@ -842,8 +852,10 @@ BOOL xf_post_connect(freerdp *instance) instance->update->EndPaint = xf_hw_end_paint; instance->update->DesktopResize = xf_hw_desktop_resize; } + pointer_cache_register_callbacks(instance->update); - if(!xfc->settings->SoftwareGdi) + + if (!xfc->settings->SoftwareGdi) { glyph_cache_register_callbacks(instance->update); brush_cache_register_callbacks(instance->update); @@ -851,16 +863,19 @@ BOOL xf_post_connect(freerdp *instance) offscreen_cache_register_callbacks(instance->update); palette_cache_register_callbacks(instance->update); } + instance->context->rail = rail_new(instance->settings); rail_register_update_callbacks(instance->context->rail, instance->update); xf_rail_register_callbacks(xfc, instance->context->rail); freerdp_channels_post_connect(channels, instance); xf_tsmf_init(xfc, xv_port); xf_cliprdr_init(xfc, channels); + EventArgsInit(&e, "xfreerdp"); e.width = settings->DesktopWidth; e.height = settings->DesktopHeight; PubSub_OnResizeWindow(((rdpContext *) xfc)->pubSub, xfc, &e); + return TRUE; } @@ -970,79 +985,102 @@ void xf_process_channel_event(rdpChannels *channels, freerdp *instance) void xf_window_free(xfContext *xfc) { - rdpContext *context = (rdpContext *) xfc; + rdpContext* context = (rdpContext*) xfc; + xf_keyboard_free(xfc); - if(xfc->gc) + + if (xfc->gc) { XFreeGC(xfc->display, xfc->gc); xfc->gc = 0; } - if(xfc->gc_mono) + + if (xfc->gc_mono) { XFreeGC(xfc->display, xfc->gc_mono); xfc->gc_mono = 0; } - if(xfc->window) + + if (xfc->window) { xf_DestroyWindow(xfc, xfc->window); xfc->window = NULL; } - if(xfc->primary) + + if (xfc->primary) { XFreePixmap(xfc->display, xfc->primary); xfc->primary = 0; } - if(xfc->bitmap_mono) + + if (xfc->bitmap_mono) { XFreePixmap(xfc->display, xfc->bitmap_mono); xfc->bitmap_mono = 0; } - if(xfc->image) + + if (xfc->image) { xfc->image->data = NULL; XDestroyImage(xfc->image); xfc->image = NULL; } - if(context->cache) + + if (context->cache) { cache_free(context->cache); context->cache = NULL; } - if(context->rail) + + if (context->rail) { rail_free(context->rail); context->rail = NULL; } - if(xfc->rfx_context) + + if (xfc->rfx) { - rfx_context_free(xfc->rfx_context); - xfc->rfx_context = NULL; + rfx_context_free(xfc->rfx); + xfc->rfx = NULL; } - if(xfc->nsc_context) + + if (xfc->nsc) { - nsc_context_free(xfc->nsc_context); - xfc->nsc_context = NULL; + nsc_context_free(xfc->nsc); + xfc->nsc = NULL; } - if(xfc->clrconv) + + if (xfc->clear) + { + clear_context_free(xfc->clear); + xfc->clear = NULL; + } + + if (xfc->clrconv) { freerdp_clrconv_free(xfc->clrconv); xfc->clrconv = NULL; } - if(xfc->hdc) + + if (xfc->hdc) + { gdi_DeleteDC(xfc->hdc); - if(xfc->xv_context) + } + + if (xfc->xv_context) { xf_tsmf_uninit(xfc); xfc->xv_context = NULL; } - if(xfc->clipboard_context) + + if (xfc->clipboard_context) { xf_cliprdr_uninit(xfc); xfc->clipboard_context = NULL; } } -void *xf_update_thread(void *arg) +void* xf_update_thread(void *arg) { int status; wMessage message; @@ -1460,12 +1498,11 @@ static void xfreerdp_client_global_init() { setlocale(LC_ALL, ""); freerdp_handle_signals(); - freerdp_channels_global_init(); } static void xfreerdp_client_global_uninit() { - freerdp_channels_global_uninit(); + } static int xfreerdp_client_start(rdpContext *context) diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index d6f0c8dd7..a4692fe3a 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -30,6 +30,7 @@ #include "xf_window.h" #include "xf_cliprdr.h" #include "xf_input.h" +#include "xf_gfx.h" #include "xf_event.h" #include "xf_input.h" @@ -189,7 +190,13 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) y = event->xexpose.y; w = event->xexpose.width; h = event->xexpose.height; - + + if (xfc->gfx) + { + xf_OutputExpose(xfc, x, y, w, h); + return TRUE; + } + if (!app) { if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) @@ -199,9 +206,7 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) } else { - XCopyArea(xfc->display, xfc->primary, - xfc->window->handle, xfc->gc, x, y, w, - h, x, y); + XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y); } } else diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index be63db5c2..1ab20af06 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -990,14 +990,12 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits XImage* image; RFX_MESSAGE* message; xfContext* xfc = (xfContext*) context; - RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) xfc->rfx_context; - NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) xfc->nsc_context; xf_lock_x11(xfc, FALSE); if (surface_bits_command->codecID == RDP_CODEC_ID_REMOTEFX) { - message = rfx_process_message(rfx_context, + message = rfx_process_message(xfc->rfx, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); XSetFunction(xfc->display, xfc->gc, GXcopy); @@ -1034,11 +1032,11 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits } XSetClipMask(xfc->display, xfc->gc, None); - rfx_message_free(rfx_context, message); + rfx_message_free(xfc->rfx, message); } else if (surface_bits_command->codecID == RDP_CODEC_ID_NSCODEC) { - nsc_process_message(nsc_context, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height, + nsc_process_message(xfc->nsc, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); XSetFunction(xfc->display, xfc->gc, GXcopy); @@ -1047,7 +1045,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits xfc->bmp_codec_nsc = (BYTE*) realloc(xfc->bmp_codec_nsc, surface_bits_command->width * surface_bits_command->height * 4); - freerdp_image_flip(nsc_context->BitmapData, xfc->bmp_codec_nsc, + freerdp_image_flip(xfc->nsc->BitmapData, xfc->bmp_codec_nsc, surface_bits_command->width, surface_bits_command->height, 32); image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, @@ -1060,13 +1058,14 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits free(xfc->bmp_codec_nsc); xfc->bmp_codec_nsc = NULL; - if (xfc->remote_app != TRUE) + if (!xfc->remote_app) { XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, surface_bits_command->destLeft, surface_bits_command->destTop); } + xf_gdi_surface_update_frame(xfc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height); diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c new file mode 100644 index 000000000..fec5036b8 --- /dev/null +++ b/client/X11/xf_gfx.c @@ -0,0 +1,672 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * X11 Graphics Pipeline + * + * Copyright 2014 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 "xf_gfx.h" + +int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics) +{ + xfContext* xfc = (xfContext*) context->custom; + + printf("xf_ResetGraphics: width: %d height: %d\n", + resetGraphics->width, resetGraphics->height); + + if (xfc->rfx) + { + rfx_context_free(xfc->rfx); + xfc->rfx = NULL; + } + + xfc->rfx = rfx_context_new(FALSE); + + xfc->rfx->width = resetGraphics->width; + xfc->rfx->height = resetGraphics->height; + rfx_context_set_pixel_format(xfc->rfx, RDP_PIXEL_FORMAT_B8G8R8A8); + + if (xfc->nsc) + { + nsc_context_free(xfc->nsc); + xfc->nsc = NULL; + } + + xfc->nsc = nsc_context_new(); + + xfc->nsc->width = resetGraphics->width; + xfc->nsc->height = resetGraphics->height; + nsc_context_set_pixel_format(xfc->nsc, RDP_PIXEL_FORMAT_B8G8R8A8); + + xfc->clear = clear_context_new(FALSE); + + region16_init(&(xfc->invalidRegion)); + + xfc->graphicsReset = TRUE; + + return 1; +} + +int xf_OutputUpdate(xfContext* xfc) +{ + UINT16 width, height; + xfGfxSurface* surface; + RECTANGLE_16 surfaceRect; + const RECTANGLE_16* extents; + + if (!xfc->graphicsReset) + return 1; + + surface = (xfGfxSurface*) xfc->gfx->GetSurfaceData(xfc->gfx, xfc->outputSurfaceId); + + if (!surface) + return -1; + + surfaceRect.left = 0; + surfaceRect.top = 0; + surfaceRect.right = xfc->width; + surfaceRect.bottom = xfc->height; + + region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect); + + XSetClipMask(xfc->display, xfc->gc, None); + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + + if (!region16_is_empty(&(xfc->invalidRegion))) + { + extents = region16_extents(&(xfc->invalidRegion)); + + width = extents->right - extents->left; + height = extents->bottom - extents->top; + + if (width > xfc->width) + width = xfc->width; + + if (height > xfc->height) + height = xfc->height; + + XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image, + extents->left, extents->top, + extents->left, extents->top, width, height); + } + + region16_clear(&(xfc->invalidRegion)); + + XSetClipMask(xfc->display, xfc->gc, None); + XSync(xfc->display, True); + + return 1; +} + +int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height) +{ + RECTANGLE_16 invalidRect; + + invalidRect.left = x; + invalidRect.top = y; + invalidRect.right = x + width; + invalidRect.bottom = y + height; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + + xf_OutputUpdate(xfc); + + return 1; +} + +int xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame) +{ + xfContext* xfc = (xfContext*) context->custom; + + xfc->inGfxFrame = TRUE; + + return 1; +} + +int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame) +{ + xfContext* xfc = (xfContext*) context->custom; + + xf_OutputUpdate(xfc); + + xfc->inGfxFrame = FALSE; + + return 1; +} + +int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + xfGfxSurface* surface; + RECTANGLE_16 invalidRect; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + + if (!surface) + return -1; + + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, + cmd->width, cmd->height, cmd->data, PIXEL_FORMAT_XRGB32, cmd->width * 4, 0, 0); + + invalidRect.left = cmd->left; + invalidRect.top = cmd->top; + invalidRect.right = cmd->right; + invalidRect.bottom = cmd->bottom; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + + if (!xfc->inGfxFrame) + xf_OutputUpdate(xfc); + + return 1; +} + +int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + int j; + UINT16 i; + RFX_RECT* rect; + RFX_TILE* tile; + int nXDst, nYDst; + int nWidth, nHeight; + int nbUpdateRects; + RFX_MESSAGE* message; + xfGfxSurface* surface; + REGION16 updateRegion; + RECTANGLE_16 updateRect; + RECTANGLE_16* updateRects; + REGION16 clippingRects; + RECTANGLE_16 clippingRect; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + + if (!surface) + return -1; + + message = rfx_process_message(xfc->rfx, cmd->data, cmd->length); + + if (!message) + return -1; + + region16_init(&clippingRects); + + for (i = 0; i < message->numRects; i++) + { + rect = &(message->rects[i]); + + clippingRect.left = cmd->left + rect->x; + clippingRect.top = cmd->top + rect->y; + clippingRect.right = clippingRect.left + rect->width; + clippingRect.bottom = clippingRect.top + rect->height; + + region16_union_rect(&clippingRects, &clippingRects, &clippingRect); + } + + for (i = 0; i < message->numTiles; i++) + { + tile = message->tiles[i]; + + updateRect.left = cmd->left + tile->x; + updateRect.top = cmd->top + tile->y; + updateRect.right = updateRect.left + 64; + updateRect.bottom = updateRect.top + 64; + + region16_init(&updateRegion); + region16_intersect_rect(&updateRegion, &clippingRects, &updateRect); + updateRects = (RECTANGLE_16*) region16_rects(&updateRegion, &nbUpdateRects); + + for (j = 0; j < nbUpdateRects; j++) + { + nXDst = updateRects[j].left; + nYDst = updateRects[j].top; + nWidth = updateRects[j].right - updateRects[j].left; + nHeight = updateRects[j].bottom - updateRects[j].top; + + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + nXDst, nYDst, nWidth, nHeight, + tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0); + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &updateRects[j]); + } + + region16_uninit(&updateRegion); + } + + rfx_message_free(xfc->rfx, message); + + if (!xfc->inGfxFrame) + xf_OutputUpdate(xfc); + + return 1; +} + +int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + int status; + UINT32 DstSize = 0; + BYTE* pDstData = NULL; + xfGfxSurface* surface; + RECTANGLE_16 invalidRect; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + + if (!surface) + return -1; + + status = clear_decompress(xfc->clear, cmd->data, cmd->length, &pDstData, &DstSize); + + printf("xf_SurfaceCommand_ClearCodec: status: %d\n", status); + + /* fill with pink for now to distinguish from the rest */ + + freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + cmd->left, cmd->top, cmd->width, cmd->height, 0xFF69B4); + + invalidRect.left = cmd->left; + invalidRect.top = cmd->top; + invalidRect.right = cmd->right; + invalidRect.bottom = cmd->bottom; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + + if (!xfc->inGfxFrame) + xf_OutputUpdate(xfc); + + return 1; +} + +int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + int status; + BYTE* DstData = NULL; + xfGfxSurface* surface; + RECTANGLE_16 invalidRect; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); + + if (!surface) + return -1; + + DstData = surface->data; + + status = planar_decompress(NULL, cmd->data, cmd->length, &DstData, + PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height); + + invalidRect.left = cmd->left; + invalidRect.top = cmd->top; + invalidRect.right = cmd->right; + invalidRect.bottom = cmd->bottom; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + + if (!xfc->inGfxFrame) + xf_OutputUpdate(xfc); + + return 1; +} + +int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) +{ + int status = 1; + xfContext* xfc = (xfContext*) context->custom; + + switch (cmd->codecId) + { + case RDPGFX_CODECID_UNCOMPRESSED: + status = xf_SurfaceCommand_Uncompressed(xfc, context, cmd); + break; + + case RDPGFX_CODECID_CAVIDEO: + status = xf_SurfaceCommand_RemoteFX(xfc, context, cmd); + break; + + case RDPGFX_CODECID_CLEARCODEC: + status = xf_SurfaceCommand_ClearCodec(xfc, context, cmd); + break; + + case RDPGFX_CODECID_PLANAR: + status = xf_SurfaceCommand_Planar(xfc, context, cmd); + break; + + case RDPGFX_CODECID_H264: + printf("xf_SurfaceCommand_H264\n"); + break; + + case RDPGFX_CODECID_ALPHA: + printf("xf_SurfaceCommand_Alpha\n"); + break; + + case RDPGFX_CODECID_CAPROGRESSIVE: + printf("xf_SurfaceCommand_Progressive\n"); + break; + + case RDPGFX_CODECID_CAPROGRESSIVE_V2: + printf("xf_SurfaceCommand_ProgressiveV2\n"); + break; + } + + return 1; +} + +int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext) +{ + printf("xf_DeleteEncodingContext\n"); + + return 1; +} + +int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface) +{ + xfGfxSurface* surface; + xfContext* xfc = (xfContext*) context->custom; + + printf("xf_CreateSurface: surfaceId: %d width: %d height: %d format: 0x%02X\n", + createSurface->surfaceId, createSurface->width, createSurface->height, createSurface->pixelFormat); + + surface = (xfGfxSurface*) calloc(1, sizeof(xfGfxSurface)); + + if (!surface) + return -1; + + surface->surfaceId = createSurface->surfaceId; + surface->width = (UINT32) createSurface->width; + surface->height = (UINT32) createSurface->height; + surface->alpha = (createSurface->pixelFormat == PIXEL_FORMAT_ARGB_8888) ? TRUE : FALSE; + + surface->scanline = (surface->width + (surface->width % 4)) * 4; + surface->data = (BYTE*) calloc(1, surface->scanline * surface->height); + + if (!surface->data) + return -1; + + surface->image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, + (char*) surface->data, surface->width, surface->height, 32, surface->scanline); + + context->SetSurfaceData(context, surface->surfaceId, (void*) surface); + + return 1; +} + +int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface) +{ + xfGfxSurface* surface = NULL; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, deleteSurface->surfaceId); + + printf("xf_DeleteSurface: surfaceId: %d\n", deleteSurface->surfaceId); + + if (surface) + { + XFree(surface->image); + free(surface->data); + free(surface); + } + + context->SetSurfaceData(context, deleteSurface->surfaceId, NULL); + + return 1; +} + +int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill) +{ + UINT16 index; + UINT32 color; + BYTE a, r, g, b; + int nWidth, nHeight; + RDPGFX_RECT16* rect; + xfGfxSurface* surface; + RECTANGLE_16 invalidRect; + xfContext* xfc = (xfContext*) context->custom; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, solidFill->surfaceId); + + printf("xf_SolidFill\n"); + + if (!surface) + return -1; + + b = solidFill->fillPixel.B; + g = solidFill->fillPixel.G; + r = solidFill->fillPixel.R; + a = solidFill->fillPixel.XA; + + color = ARGB32(a, r, g, b); + + for (index = 0; index < solidFill->fillRectCount; index++) + { + rect = &(solidFill->fillRects[index]); + + nWidth = rect->right - rect->left; + nHeight = rect->bottom - rect->top; + + invalidRect.left = rect->left; + invalidRect.top = rect->top; + invalidRect.right = rect->right; + invalidRect.bottom = rect->bottom; + + freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + rect->left, rect->top, nWidth, nHeight, color); + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + } + + if (!xfc->inGfxFrame) + xf_OutputUpdate(xfc); + + return 1; +} + +int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface) +{ + UINT16 index; + int nWidth, nHeight; + RDPGFX_RECT16* rectSrc; + RDPGFX_POINT16* destPt; + RECTANGLE_16 invalidRect; + xfGfxSurface* surfaceSrc; + xfGfxSurface* surfaceDst; + xfContext* xfc = (xfContext*) context->custom; + + rectSrc = &(surfaceToSurface->rectSrc); + destPt = &surfaceToSurface->destPts[0]; + + surfaceSrc = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc); + + if (surfaceToSurface->surfaceIdSrc != surfaceToSurface->surfaceIdDest) + surfaceDst = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdDest); + else + surfaceDst = surfaceSrc; + + if (!surfaceSrc || !surfaceDst) + return -1; + + nWidth = rectSrc->right - rectSrc->left + 1; + nHeight = rectSrc->bottom - rectSrc->top + 1; + + for (index = 0; index < surfaceToSurface->destPtsCount; index++) + { + destPt = &surfaceToSurface->destPts[index]; + + freerdp_image_copy(surfaceDst->data, PIXEL_FORMAT_XRGB32, surfaceDst->scanline, + destPt->x, destPt->y, nWidth, nHeight, surfaceSrc->data, PIXEL_FORMAT_XRGB32, + surfaceSrc->scanline, rectSrc->left, rectSrc->top); + + invalidRect.left = destPt->x; + invalidRect.top = destPt->y; + invalidRect.right = destPt->x + rectSrc->right; + invalidRect.bottom = destPt->y + rectSrc->bottom; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + } + + if (!xfc->inGfxFrame) + xf_OutputUpdate(xfc); + + return 1; +} + +int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache) +{ + RDPGFX_RECT16* rect; + xfGfxSurface* surface; + xfGfxCacheEntry* cacheEntry; + + rect = &(surfaceToCache->rectSrc); + + surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId); + + //printf("xf_SurfaceToCache: cacheKey: 0x%016X cacheSlot: %ld\n", + // surfaceToCache->cacheKey, surfaceToCache->cacheSlot); + + if (!surface) + return -1; + + cacheEntry = (xfGfxCacheEntry*) calloc(1, sizeof(xfGfxCacheEntry)); + + if (!cacheEntry) + return -1; + + cacheEntry->width = (UINT32) (rect->right - rect->left); + cacheEntry->height = (UINT32) (rect->bottom - rect->top); + cacheEntry->alpha = surface->alpha; + + cacheEntry->scanline = (cacheEntry->width + (cacheEntry->width % 4)) * 4; + cacheEntry->data = (BYTE*) calloc(1, surface->scanline * surface->height); + + if (!cacheEntry->data) + return -1; + + freerdp_image_copy(cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, + 0, 0, cacheEntry->width, cacheEntry->height, surface->data, + PIXEL_FORMAT_XRGB32, surface->scanline, rect->left, rect->top); + + context->SetCacheSlotData(context, surfaceToCache->cacheSlot, (void*) cacheEntry); + + return 1; +} + +int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface) +{ + UINT16 index; + RDPGFX_POINT16* destPt; + xfGfxSurface* surface; + xfGfxCacheEntry* cacheEntry; + RECTANGLE_16 invalidRect; + xfContext* xfc = (xfContext*) context->custom; + + surface = (xfGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId); + cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot); + + //printf("xf_CacheToSurface: cacheEntry: %d\n", + // cacheToSurface->cacheSlot); + + if (!surface || !cacheEntry) + return -1; + + for (index = 0; index < cacheToSurface->destPtsCount; index++) + { + destPt = &cacheToSurface->destPts[index]; + + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + destPt->x, destPt->y, cacheEntry->width, cacheEntry->height, + cacheEntry->data, PIXEL_FORMAT_XRGB32, cacheEntry->scanline, 0, 0); + + invalidRect.left = destPt->x; + invalidRect.top = destPt->y; + invalidRect.right = destPt->x + cacheEntry->width - 1; + invalidRect.bottom = destPt->y + cacheEntry->height - 1; + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + } + + if (!xfc->inGfxFrame) + xf_OutputUpdate(xfc); + + return 1; +} + +int xf_CacheImportReply(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply) +{ + return 1; +} + +int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry) +{ + xfGfxCacheEntry* cacheEntry; + + //printf("xf_EvictCacheEntry\n"); + + cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, evictCacheEntry->cacheSlot); + + if (cacheEntry) + { + free(cacheEntry->data); + free(cacheEntry); + } + + context->SetCacheSlotData(context, evictCacheEntry->cacheSlot, NULL); + + return 1; +} + +int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput) +{ + xfContext* xfc = (xfContext*) context->custom; + + xfc->outputSurfaceId = surfaceToOutput->surfaceId; + + return 1; +} + +int xf_MapSurfaceToWindow(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow) +{ + return 1; +} + +void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx) +{ + xfc->gfx = gfx; + gfx->custom = (void*) xfc; + + gfx->ResetGraphics = xf_ResetGraphics; + gfx->StartFrame = xf_StartFrame; + gfx->EndFrame = xf_EndFrame; + gfx->SurfaceCommand = xf_SurfaceCommand; + gfx->DeleteEncodingContext = xf_DeleteEncodingContext; + gfx->CreateSurface = xf_CreateSurface; + gfx->DeleteSurface = xf_DeleteSurface; + gfx->SolidFill = xf_SolidFill; + gfx->SurfaceToSurface = xf_SurfaceToSurface; + gfx->SurfaceToCache = xf_SurfaceToCache; + gfx->CacheToSurface = xf_CacheToSurface; + gfx->CacheImportReply = xf_CacheImportReply; + gfx->EvictCacheEntry = xf_EvictCacheEntry; + gfx->MapSurfaceToOutput = xf_MapSurfaceToOutput; + gfx->MapSurfaceToWindow = xf_MapSurfaceToWindow; + + region16_init(&(xfc->invalidRegion)); +} + +void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx) +{ + region16_uninit(&(xfc->invalidRegion)); + + gfx->custom = NULL; + xfc->gfx = NULL; +} diff --git a/client/X11/xf_gfx.h b/client/X11/xf_gfx.h new file mode 100644 index 000000000..ba937ee92 --- /dev/null +++ b/client/X11/xf_gfx.h @@ -0,0 +1,54 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * X11 Graphics Pipeline + * + * Copyright 2014 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 __XF_GRAPHICS_PIPELINE_H +#define __XF_GRAPHICS_PIPELINE_H + +#include "xf_client.h" +#include "xfreerdp.h" + +struct xf_gfx_surface +{ + UINT16 surfaceId; + UINT32 width; + UINT32 height; + BOOL alpha; + BYTE* data; + XImage* image; + int scanline; +}; +typedef struct xf_gfx_surface xfGfxSurface; + +struct xf_gfx_cache_entry +{ + UINT64 cacheKey; + UINT32 width; + UINT32 height; + BOOL alpha; + BYTE* data; + int scanline; +}; +typedef struct xf_gfx_cache_entry xfGfxCacheEntry; + +int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height); + +void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx); +void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx); + +#endif /* __XF_GRAPHICS_PIPELINE_H */ diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index 2c281d33d..fa24d967c 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -145,8 +145,8 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, break; case RDP_CODEC_ID_REMOTEFX: - rfx_context_set_pixel_format(xfc->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8); - msg = rfx_process_message(xfc->rfx_context, data, length); + rfx_context_set_pixel_format(xfc->rfx, RDP_PIXEL_FORMAT_B8G8R8A8); + msg = rfx_process_message(xfc->rfx, data, length); if (msg == NULL) { @@ -166,7 +166,7 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, src++; } } - rfx_message_free(xfc->rfx_context, msg); + rfx_message_free(xfc->rfx, msg); } break; diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index ba42368da..7df1f8768 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -299,15 +299,16 @@ static const char *get_shm_id() return shm_id; } -xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int height, BOOL decorations) +xfWindow* xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int height, BOOL decorations) { - xfWindow *window; + xfWindow* window; XEvent xevent; - rdpSettings *settings; - window = (xfWindow *) malloc(sizeof(xfWindow)); - ZeroMemory(window, sizeof(xfWindow)); + rdpSettings* settings; + window = (xfWindow*) calloc(1, sizeof(xfWindow)); + settings = xfc->instance->settings; - if(window) + + if (window) { int input_mask; XClassHint *class_hints; @@ -322,48 +323,65 @@ xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int heig xfc->workArea.x, xfc->workArea.y, xfc->workArea.width, xfc->workArea.height, 0, xfc->depth, InputOutput, xfc->visual, CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap | CWBorderPixel | CWWinGravity | CWBitGravity, &xfc->attribs); + window->shmid = shm_open(get_shm_id(), O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE); - if(window->shmid < 0) + + if (window->shmid < 0) { DEBUG_X11("xf_CreateDesktopWindow: failed to get access to shared memory - shmget()\n"); } else { + void* mem; + ftruncate(window->shmid, sizeof(window->handle)); - window->xfwin = mmap(0, sizeof(window->handle), PROT_READ | PROT_WRITE, MAP_SHARED, window->shmid, 0); - if(window->xfwin == (int *) -1) + + mem = mmap(0, sizeof(window->handle), PROT_READ | PROT_WRITE, MAP_SHARED, window->shmid, 0); + + if (mem == ((int*) -1)) { DEBUG_X11("xf_CreateDesktopWindow: failed to assign pointer to the memory address - shmat()\n"); } else { + window->xfwin = mem; *window->xfwin = window->handle; } } + class_hints = XAllocClassHint(); - if(class_hints) + + if (class_hints) { class_hints->res_name = "xfreerdp"; - if(xfc->instance->settings->WmClass) + + if (xfc->instance->settings->WmClass) class_hints->res_class = xfc->instance->settings->WmClass; else class_hints->res_class = "xfreerdp"; + XSetClassHint(xfc->display, window->handle, class_hints); XFree(class_hints); } + xf_ResizeDesktopWindow(xfc, window, width, height); xf_SetWindowDecorations(xfc, window, decorations); xf_SetWindowPID(xfc, window, 0); + input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | VisibilityChangeMask | FocusChangeMask | StructureNotifyMask | PointerMotionMask | ExposureMask | PropertyChangeMask; - if(xfc->grab_keyboard) + + if (xfc->grab_keyboard) input_mask |= EnterWindowMask | LeaveWindowMask; + XChangeProperty(xfc->display, window->handle, xfc->_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, (BYTE *) xf_icon_prop, ARRAYSIZE(xf_icon_prop)); - if(xfc->settings->ParentWindowId) + + if (xfc->settings->ParentWindowId) XReparentWindow(xfc->display, window->handle, (Window) xfc->settings->ParentWindowId, 0, 0); + XSelectInput(xfc->display, window->handle, input_mask); XClearWindow(xfc->display, window->handle); XMapWindow(xfc->display, window->handle); @@ -382,15 +400,14 @@ xfWindow *xf_CreateDesktopWindow(xfContext *xfc, char *name, int width, int heig * monitor instead of the upper-left monitor for remote app mode(which uses all monitors). * This extra call after the window is mapped will position the login window correctly */ - if(xfc->instance->settings->RemoteApplicationMode) + if (xfc->instance->settings->RemoteApplicationMode) { XMoveWindow(xfc->display, window->handle, 0, 0); } - else - if(settings->DesktopPosX || settings->DesktopPosY) - { - XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY); - } + else if(settings->DesktopPosX || settings->DesktopPosY) + { + XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY); + } } xf_SetWindowText(xfc, window, name); return window; @@ -822,25 +839,33 @@ BOOL xf_IsWindowBorder(xfContext *xfc, xfWindow *xfw, int x, int y) void xf_DestroyWindow(xfContext *xfc, xfWindow *window) { - if(window == NULL) + if (!window) return; - if(xfc->window == window) + + if (xfc->window == window) xfc->window = NULL; - if(window->gc) + + if (window->gc) XFreeGC(xfc->display, window->gc); - if(window->handle) + + if (window->handle) { XUnmapWindow(xfc->display, window->handle); XDestroyWindow(xfc->display, window->handle); } - free(window); - if(window->xfwin) + + if (window->xfwin) munmap(0, sizeof(*window->xfwin)); - if(window->shmid >= 0) + + if (window->shmid >= 0) close(window->shmid); + shm_unlink(get_shm_id()); - window->xfwin = -1; + + window->xfwin = (Window*) -1; window->shmid = -1; + + free(window); } rdpWindow *xf_rdpWindowFromWindow(xfContext *xfc, Window wnd) diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index aa01ae905..a1e6ebf16 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -28,6 +28,14 @@ typedef struct xf_context xfContext; #include "xf_monitor.h" #include "xf_channels.h" +#include +#include +#include +#include +#include +#include +#include + struct xf_WorkArea { UINT32 x; @@ -103,6 +111,10 @@ struct xf_context HGDI_DC hdc; BYTE* primary_buffer; + REGION16 invalidRegion; + BOOL inGfxFrame; + BOOL graphicsReset; + UINT16 outputSurfaceId; BOOL frame_begin; UINT16 frame_x1; @@ -137,8 +149,9 @@ struct xf_context VIRTUAL_SCREEN vscreen; BYTE* bmp_codec_none; BYTE* bmp_codec_nsc; - void* rfx_context; - void* nsc_context; + RFX_CONTEXT* rfx; + NSC_CONTEXT* nsc; + CLEAR_CONTEXT* clear; void* xv_context; void* clipboard_context; @@ -168,6 +181,7 @@ struct xf_context /* Channels */ RdpeiClientContext* rdpei; + RdpgfxClientContext* gfx; }; void xf_create_window(xfContext* xfc); diff --git a/client/common/cmdline.c b/client/common/cmdline.c index c86dc5db9..34bbd0b6b 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1609,6 +1609,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, CommandLineSwitchCase(arg, "gfx") { settings->SupportGraphicsPipeline = TRUE; + settings->FastPathOutput = TRUE; + settings->ColorDepth = 32; + settings->LargePointerFlag = TRUE; + settings->FrameMarkerCommandEnabled = TRUE; } CommandLineSwitchCase(arg, "rfx") { diff --git a/client/common/file.c b/client/common/file.c index 3d018b845..c4937343a 100644 --- a/client/common/file.c +++ b/client/common/file.c @@ -63,7 +63,7 @@ BOOL freerdp_client_rdp_file_set_integer(rdpFile* file, const char* name, int va file->ScreenModeId = value; else if (_stricmp(name, "span monitors") == 0) file->SpanMonitors = value; - else if (_stricmp(name, "smartsizing") == 0) + else if (_stricmp(name, "smart sizing") == 0) file->SmartSizing = value; else if (_stricmp(name, "enablesuperpan") == 0) file->EnableSuperSpan = value; diff --git a/client/iOS/FreeRDP/ios_freerdp.m b/client/iOS/FreeRDP/ios_freerdp.m index a6eac2ce8..fa8c75383 100644 --- a/client/iOS/FreeRDP/ios_freerdp.m +++ b/client/iOS/FreeRDP/ios_freerdp.m @@ -303,12 +303,11 @@ void ios_freerdp_free(freerdp* instance) void ios_init_freerdp() { signal(SIGPIPE, SIG_IGN); - freerdp_channels_global_init(); freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); } void ios_uninit_freerdp() { - freerdp_channels_global_uninit(); + } diff --git a/cunit/test_cliprdr.c b/cunit/test_cliprdr.c index 6b329a8fd..85fb580ef 100644 --- a/cunit/test_cliprdr.c +++ b/cunit/test_cliprdr.c @@ -31,13 +31,11 @@ int init_cliprdr_suite(void) { - freerdp_channels_global_init(); return 0; } int clean_cliprdr_suite(void) { - freerdp_channels_global_uninit(); return 0; } diff --git a/cunit/test_drdynvc.c b/cunit/test_drdynvc.c index fcbadcf22..64b5a59a2 100644 --- a/cunit/test_drdynvc.c +++ b/cunit/test_drdynvc.c @@ -31,13 +31,11 @@ int init_drdynvc_suite(void) { - freerdp_channels_global_init(); return 0; } int clean_drdynvc_suite(void) { - freerdp_channels_global_uninit(); return 0; } diff --git a/cunit/test_rail.c b/cunit/test_rail.c index 601024d5c..461701c51 100644 --- a/cunit/test_rail.c +++ b/cunit/test_rail.c @@ -46,13 +46,11 @@ int init_rail_suite(void) { - freerdp_channels_global_init(); return 0; } int clean_rail_suite(void) { - freerdp_channels_global_uninit(); return 0; } diff --git a/include/freerdp/channels/channels.h b/include/freerdp/channels/channels.h index c136411dd..60b481d17 100644 --- a/include/freerdp/channels/channels.h +++ b/include/freerdp/channels/channels.h @@ -32,8 +32,6 @@ extern "C" { #endif -FREERDP_API int freerdp_channels_global_init(void); -FREERDP_API int freerdp_channels_global_uninit(void); FREERDP_API rdpChannels* freerdp_channels_new(void); FREERDP_API void freerdp_channels_free(rdpChannels* channels); FREERDP_API int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, diff --git a/include/freerdp/channels/rdpgfx.h b/include/freerdp/channels/rdpgfx.h index ef38bf0a3..e4070194b 100644 --- a/include/freerdp/channels/rdpgfx.h +++ b/include/freerdp/channels/rdpgfx.h @@ -60,6 +60,7 @@ typedef struct _RDPGFX_COLOR32 RDPGFX_COLOR32; typedef BYTE RDPGFX_PIXELFORMAT; +#define RDPGFX_CMDID_UNUSED_0000 0x0000 #define RDPGFX_CMDID_WIRETOSURFACE_1 0x0001 #define RDPGFX_CMDID_WIRETOSURFACE_2 0x0002 #define RDPGFX_CMDID_DELETEENCODINGCONTEXT 0x0003 @@ -79,8 +80,11 @@ typedef BYTE RDPGFX_PIXELFORMAT; #define RDPGFX_CMDID_CACHEIMPORTREPLY 0x0011 #define RDPGFX_CMDID_CAPSADVERTISE 0x0012 #define RDPGFX_CMDID_CAPSCONFIRM 0x0013 +#define RDPGFX_CMDID_UNUSED_0014 0x0014 #define RDPGFX_CMDID_MAPSURFACETOWINDOW 0x0015 +#define RDPGFX_HEADER_SIZE 8 + struct _RDPGFX_HEADER { UINT16 cmdId; @@ -96,11 +100,12 @@ typedef struct _RDPGFX_HEADER RDPGFX_HEADER; #define RDPGFX_CAPVERSION_8 0x00080004 #define RDPGFX_CAPVERSION_81 0x00080105 +#define RDPGFX_CAPSET_SIZE 12 + struct _RDPGFX_CAPSET { UINT32 version; - UINT32 capsDataLength; - /* capsData (variable) */ + UINT32 flags; }; typedef struct _RDPGFX_CAPSET RDPGFX_CAPSET; @@ -160,6 +165,23 @@ struct _RDPGFX_WIRE_TO_SURFACE_PDU_2 }; typedef struct _RDPGFX_WIRE_TO_SURFACE_PDU_2 RDPGFX_WIRE_TO_SURFACE_PDU_2; +struct _RDPGFX_SURFACE_COMMAND +{ + UINT32 surfaceId; + UINT32 codecId; + UINT32 contextId; + UINT32 format; + UINT32 left; + UINT32 top; + UINT32 right; + UINT32 bottom; + UINT32 width; + UINT32 height; + UINT32 length; + BYTE* data; +}; +typedef struct _RDPGFX_SURFACE_COMMAND RDPGFX_SURFACE_COMMAND; + struct _RDPGFX_DELETE_ENCODING_CONTEXT_PDU { UINT16 surfaceId; @@ -167,14 +189,14 @@ struct _RDPGFX_DELETE_ENCODING_CONTEXT_PDU }; typedef struct _RDPGFX_DELETE_ENCODING_CONTEXT_PDU RDPGFX_DELETE_ENCODING_CONTEXT_PDU; -struct _RDPGFX_SOLIDFILL_PDU +struct _RDPGFX_SOLID_FILL_PDU { UINT16 surfaceId; RDPGFX_COLOR32 fillPixel; UINT16 fillRectCount; RDPGFX_RECT16* fillRects; }; -typedef struct _RDPGFX_SOLIDFILL_PDU RDPGFX_SOLIDFILL_PDU; +typedef struct _RDPGFX_SOLID_FILL_PDU RDPGFX_SOLID_FILL_PDU; struct _RDPGFX_SURFACE_TO_SURFACE_PDU { @@ -254,8 +276,7 @@ struct _RDPGFX_RESET_GRAPHICS_PDU UINT32 width; UINT32 height; UINT32 monitorCount; - /* monitorDefArray */ - /* pad */ + MONITOR_DEF* monitorDefArray; }; typedef struct _RDPGFX_RESET_GRAPHICS_PDU RDPGFX_RESET_GRAPHICS_PDU; @@ -292,14 +313,13 @@ typedef struct _RDPGFX_CACHE_IMPORT_REPLY_PDU RDPGFX_CACHE_IMPORT_REPLY_PDU; struct _RDPGFX_CAPS_ADVERTISE_PDU { UINT16 capsSetCount; - /* capsSets */ + RDPGFX_CAPSET* capsSets; }; typedef struct _RDPGFX_CAPS_ADVERTISE_PDU RDPGFX_CAPS_ADVERTISE_PDU; struct _RDPGFX_CAPS_CONFIRM_PDU { - RDPGFX_CAPSET* capSet; - /* capSet */ + RDPGFX_CAPSET* capsSet; }; typedef struct _RDPGFX_CAPS_CONFIRM_PDU RDPGFX_CAPS_CONFIRM_PDU; diff --git a/include/freerdp/client/rdpgfx.h b/include/freerdp/client/rdpgfx.h index b9e7c70e8..f44cfbbeb 100644 --- a/include/freerdp/client/rdpgfx.h +++ b/include/freerdp/client/rdpgfx.h @@ -28,14 +28,54 @@ typedef struct _rdpgfx_client_context RdpgfxClientContext; -typedef UINT32 (*pcRdpgfxGetVersion)(RdpgfxClientContext* context); +typedef int (*pcRdpgfxResetGraphics)(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics); +typedef int (*pcRdpgfxStartFrame)(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame); +typedef int (*pcRdpgfxEndFrame)(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame); +typedef int (*pcRdpgfxSurfaceCommand)(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd); +typedef int (*pcRdpgfxDeleteEncodingContext)(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext); +typedef int (*pcRdpgfxCreateSurface)(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface); +typedef int (*pcRdpgfxDeleteSurface)(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface); +typedef int (*pcRdpgfxSolidFill)(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill); +typedef int (*pcRdpgfxSurfaceToSurface)(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface); +typedef int (*pcRdpgfxSurfaceToCache)(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache); +typedef int (*pcRdpgfxCacheToSurface)(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface); +typedef int (*pcRdpgfxCacheImportOffer)(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_OFFER_PDU* cacheImportOffer); +typedef int (*pcRdpgfxCacheImportReply)(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply); +typedef int (*pcRdpgfxEvictCacheEntry)(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry); +typedef int (*pcRdpgfxMapSurfaceToOutput)(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput); +typedef int (*pcRdpgfxMapSurfaceToWindow)(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow); + +typedef int (*pcRdpgfxSetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId, void* pData); +typedef void* (*pcRdpgfxGetSurfaceData)(RdpgfxClientContext* context, UINT16 surfaceId); +typedef int (*pcRdpgfxSetCacheSlotData)(RdpgfxClientContext* context, UINT16 cacheSlot, void* pData); +typedef void* (*pcRdpgfxGetCacheSlotData)(RdpgfxClientContext* context, UINT16 cacheSlot); struct _rdpgfx_client_context { void* handle; void* custom; - pcRdpgfxGetVersion GetVersion; + pcRdpgfxResetGraphics ResetGraphics; + pcRdpgfxStartFrame StartFrame; + pcRdpgfxEndFrame EndFrame; + pcRdpgfxSurfaceCommand SurfaceCommand; + pcRdpgfxDeleteEncodingContext DeleteEncodingContext; + pcRdpgfxCreateSurface CreateSurface; + pcRdpgfxDeleteSurface DeleteSurface; + pcRdpgfxSolidFill SolidFill; + pcRdpgfxSurfaceToSurface SurfaceToSurface; + pcRdpgfxSurfaceToCache SurfaceToCache; + pcRdpgfxCacheToSurface CacheToSurface; + pcRdpgfxCacheImportOffer CacheImportOffer; + pcRdpgfxCacheImportReply CacheImportReply; + pcRdpgfxEvictCacheEntry EvictCacheEntry; + pcRdpgfxMapSurfaceToOutput MapSurfaceToOutput; + pcRdpgfxMapSurfaceToWindow MapSurfaceToWindow; + + pcRdpgfxSetSurfaceData SetSurfaceData; + pcRdpgfxGetSurfaceData GetSurfaceData; + pcRdpgfxSetCacheSlotData SetCacheSlotData; + pcRdpgfxGetCacheSlotData GetCacheSlotData; }; #endif /* FREERDP_CHANNEL_CLIENT_RDPGFX_H */ diff --git a/include/freerdp/codec/bitmap.h b/include/freerdp/codec/bitmap.h index 6e09f2d8c..d25c28b84 100644 --- a/include/freerdp/codec/bitmap.h +++ b/include/freerdp/codec/bitmap.h @@ -46,4 +46,7 @@ FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, FREERDP_API BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight); FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context); +FREERDP_API int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize, + BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight); + #endif /* FREERDP_CODEC_BITMAP_H */ diff --git a/include/freerdp/codec/clear.h b/include/freerdp/codec/clear.h new file mode 100644 index 000000000..bb1550a25 --- /dev/null +++ b/include/freerdp/codec/clear.h @@ -0,0 +1,57 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * ClearCodec Bitmap Compression + * + * Copyright 2014 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_CODEC_CLEAR_H +#define FREERDP_CODEC_CLEAR_H + +#include +#include + +#define CLEARCODEC_FLAG_GLYPH_INDEX 0x01 +#define CLEARCODEC_FLAG_GLYPH_HIT 0x02 +#define CLEARCODEC_FLAG_CACHE_RESET 0x03 + +struct _CLEAR_CONTEXT +{ + BOOL Compressor; + UINT32 VBarStorageCursor; + void* VBarStorage[32768]; + UINT32 ShortVBarStorageCursor; + void* ShortVBarStorage[16384]; +}; +typedef struct _CLEAR_CONTEXT CLEAR_CONTEXT; + +#ifdef __cplusplus +extern "C" { +#endif + +FREERDP_API int clear_compress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize); +FREERDP_API int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize); + +FREERDP_API void clear_context_reset(CLEAR_CONTEXT* clear); + +FREERDP_API CLEAR_CONTEXT* clear_context_new(BOOL Compressor); +FREERDP_API void clear_context_free(CLEAR_CONTEXT* clear); + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_CODEC_CLEAR_H */ + diff --git a/include/freerdp/codec/color.h b/include/freerdp/codec/color.h index fc14f1518..4fdaf8aa9 100644 --- a/include/freerdp/codec/color.h +++ b/include/freerdp/codec/color.h @@ -33,10 +33,10 @@ #define FREERDP_PIXEL_FLIP_VERTICAL 1 #define FREERDP_PIXEL_FLIP_HORIZONTAL 2 -#define FREERDP_PIXEL_FORMAT(_bpp, _type, _a, _r, _g, _b) \ - ((_bpp << 24) | (_type << 16) | (_a << 12) | (_r << 8) | (_g << 4) | (_b)) +#define FREERDP_PIXEL_FORMAT(_flip, _bpp, _type, _a, _r, _g, _b) \ + ((_flip << 30) | (_bpp << 24) | (_type << 16) | (_a << 12) | (_r << 8) | (_g << 4) | (_b)) -#define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 30) & 0x02) +#define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 30) & 0x03) #define FREERDP_PIXEL_FORMAT_BPP(_format) (((_format) >> 24) & 0x3F) #define FREERDP_PIXEL_FORMAT_TYPE(_format) (((_format) >> 16) & 0xFF) #define FREERDP_PIXEL_FORMAT_A(_format) (((_format) >> 12) & 0x0F) @@ -54,84 +54,110 @@ /* 32bpp formats */ -#define PIXEL_FORMAT_A8R8G8B8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 8, 8, 8, 8) -#define PIXEL_FORMAT_ARGB32 PIXEL_FORMAT_A8R8G8B8 +#define PIXEL_FORMAT_A8R8G8B8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 8, 8, 8, 8) +#define PIXEL_FORMAT_A8R8G8B8 PIXEL_FORMAT_A8R8G8B8_F(0) +#define PIXEL_FORMAT_ARGB32 PIXEL_FORMAT_A8R8G8B8 +#define PIXEL_FORMAT_A8R8G8B8_VF PIXEL_FORMAT_A8R8G8B8_F(1) +#define PIXEL_FORMAT_ARGB32_VF PIXEL_FORMAT_A8R8G8B8_VF -#define PIXEL_FORMAT_X8R8G8B8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8) -#define PIXEL_FORMAT_XRGB32 PIXEL_FORMAT_X8R8G8B8 -#define PIXEL_FORMAT_RGB32 PIXEL_FORMAT_XRGB32 +#define PIXEL_FORMAT_X8R8G8B8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8) +#define PIXEL_FORMAT_X8R8G8B8 PIXEL_FORMAT_X8R8G8B8_F(0) +#define PIXEL_FORMAT_XRGB32 PIXEL_FORMAT_X8R8G8B8 +#define PIXEL_FORMAT_RGB32 PIXEL_FORMAT_XRGB32 +#define PIXEL_FORMAT_X8R8G8B8_VF PIXEL_FORMAT_X8R8G8B8_F(1) +#define PIXEL_FORMAT_XRGB32_VF PIXEL_FORMAT_X8R8G8B8_VF +#define PIXEL_FORMAT_RGB32_VF PIXEL_FORMAT_XRGB32_VF -#define PIXEL_FORMAT_A8B8G8R8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 8, 8, 8, 8) -#define PIXEL_FORMAT_ABGR32 PIXEL_FORMAT_A8B8G8R8 +#define PIXEL_FORMAT_A8B8G8R8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 8, 8, 8, 8) +#define PIXEL_FORMAT_A8B8G8R8 PIXEL_FORMAT_A8B8G8R8_F(0) +#define PIXEL_FORMAT_ABGR32 PIXEL_FORMAT_A8B8G8R8 +#define PIXEL_FORMAT_A8B8G8R8_VF PIXEL_FORMAT_A8B8G8R8_F(1) +#define PIXEL_FORMAT_ABGR32_VF PIXEL_FORMAT_A8B8G8R8_VF -#define PIXEL_FORMAT_X8B8G8R8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8) -#define PIXEL_FORMAT_XBGR32 PIXEL_FORMAT_X8B8G8R8 -#define PIXEL_FORMAT_BGR32 PIXEL_FORMAT_XBGR32 +#define PIXEL_FORMAT_X8B8G8R8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8) +#define PIXEL_FORMAT_X8B8G8R8 PIXEL_FORMAT_X8B8G8R8_F(0) +#define PIXEL_FORMAT_XBGR32 PIXEL_FORMAT_X8B8G8R8 +#define PIXEL_FORMAT_BGR32 PIXEL_FORMAT_XBGR32 +#define PIXEL_FORMAT_X8B8G8R8_VF PIXEL_FORMAT_X8B8G8R8_F(1) +#define PIXEL_FORMAT_XBGR32_VF PIXEL_FORMAT_X8B8G8R8_VF +#define PIXEL_FORMAT_BGR32_VF PIXEL_FORMAT_XBGR32_VF -#define PIXEL_FORMAT_B8G8R8A8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 8, 8, 8, 8) -#define PIXEL_FORMAT_BGRA32 PIXEL_FORMAT_B8G8R8A8 +#define PIXEL_FORMAT_B8G8R8A8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 8, 8, 8, 8) +#define PIXEL_FORMAT_B8G8R8A8 PIXEL_FORMAT_B8G8R8A8_F(0) +#define PIXEL_FORMAT_BGRA32 PIXEL_FORMAT_B8G8R8A8 +#define PIXEL_FORMAT_B8G8R8A8_VF PIXEL_FORMAT_B8G8R8A8_F(1) +#define PIXEL_FORMAT_BGRA32_VF PIXEL_FORMAT_B8G8R8A8_VF -#define PIXEL_FORMAT_B8G8R8X8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 0, 8, 8, 8) -#define PIXEL_FORMAT_BGRX32 PIXEL_FORMAT_B8G8R8X8 +#define PIXEL_FORMAT_B8G8R8X8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 0, 8, 8, 8) +#define PIXEL_FORMAT_B8G8R8X8 PIXEL_FORMAT_B8G8R8X8_F(0) +#define PIXEL_FORMAT_BGRX32 PIXEL_FORMAT_B8G8R8X8 +#define PIXEL_FORMAT_B8G8R8X8_VF PIXEL_FORMAT_B8G8R8X8_F(1) +#define PIXEL_FORMAT_BGRX32_VF PIXEL_FORMAT_B8G8R8X8_VF -#define PIXEL_FORMAT_R8G8B8A8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 8, 8, 8, 8) -#define PIXEL_FORMAT_RGBA32 PIXEL_FORMAT_R8G8B8A8 +#define PIXEL_FORMAT_R8G8B8A8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 8, 8, 8, 8) +#define PIXEL_FORMAT_R8G8B8A8 PIXEL_FORMAT_R8G8B8A8_F(0) +#define PIXEL_FORMAT_RGBA32 PIXEL_FORMAT_R8G8B8A8 +#define PIXEL_FORMAT_R8G8B8A8_VF PIXEL_FORMAT_R8G8B8A8_F(1) +#define PIXEL_FORMAT_RGBA32_VF PIXEL_FORMAT_R8G8B8A8_VF -#define PIXEL_FORMAT_R8G8B8X8 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 0, 8, 8, 8) -#define PIXEL_FORMAT_RGBX32 PIXEL_FORMAT_R8G8B8X8 +#define PIXEL_FORMAT_R8G8B8X8_F(_flip) FREERDP_PIXEL_FORMAT(_flip, 32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 0, 8, 8, 8) +#define PIXEL_FORMAT_R8G8B8X8 PIXEL_FORMAT_R8G8B8X8_F(0) +#define PIXEL_FORMAT_RGBX32 PIXEL_FORMAT_R8G8B8X8 +#define PIXEL_FORMAT_R8G8B8X8_VF PIXEL_FORMAT_R8G8B8X8_F(1) +#define PIXEL_FORMAT_RGBX32_VF PIXEL_FORMAT_R8G8B8X8_VF /* 24bpp formats */ -#define PIXEL_FORMAT_R8G8B8 FREERDP_PIXEL_FORMAT(24, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8) -#define PIXEL_FORMAT_RGB24 PIXEL_FORMAT_R8G8B8 +#define PIXEL_FORMAT_R8G8B8 FREERDP_PIXEL_FORMAT(0, 24, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8) +#define PIXEL_FORMAT_RGB24 PIXEL_FORMAT_R8G8B8 -#define PIXEL_FORMAT_B8G8R8 FREERDP_PIXEL_FORMAT(24, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8) -#define PIXEL_FORMAT_BGR24 PIXEL_FORMAT_B8G8R8 +#define PIXEL_FORMAT_B8G8R8 FREERDP_PIXEL_FORMAT(0, 24, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8) +#define PIXEL_FORMAT_BGR24 PIXEL_FORMAT_B8G8R8 /* 16bpp formats */ -#define PIXEL_FORMAT_R5G6B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 6, 5) -#define PIXEL_FORMAT_RGB565 PIXEL_FORMAT_R5G6B5 -#define PIXEL_FORMAT_RGB16 PIXEL_FORMAT_R5G6B5 +#define PIXEL_FORMAT_R5G6B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 6, 5) +#define PIXEL_FORMAT_RGB565 PIXEL_FORMAT_R5G6B5 +#define PIXEL_FORMAT_RGB16 PIXEL_FORMAT_R5G6B5 -#define PIXEL_FORMAT_B5G6R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 6, 5) -#define PIXEL_FORMAT_BGR565 PIXEL_FORMAT_B5G6R5 -#define PIXEL_FORMAT_BGR16 PIXEL_FORMAT_B5G6R5 +#define PIXEL_FORMAT_B5G6R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 6, 5) +#define PIXEL_FORMAT_BGR565 PIXEL_FORMAT_B5G6R5 +#define PIXEL_FORMAT_BGR16 PIXEL_FORMAT_B5G6R5 -#define PIXEL_FORMAT_A1R5G5B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 1, 5, 5, 5) -#define PIXEL_FORMAT_ARGB555 PIXEL_FORMAT_A1R5G5B5 -#define PIXEL_FORMAT_ARGB15 PIXEL_FORMAT_A1R5G5B5 +#define PIXEL_FORMAT_A1R5G5B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 1, 5, 5, 5) +#define PIXEL_FORMAT_ARGB555 PIXEL_FORMAT_A1R5G5B5 +#define PIXEL_FORMAT_ARGB15 PIXEL_FORMAT_A1R5G5B5 -#define PIXEL_FORMAT_X1R5G5B5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 5, 5) -#define PIXEL_FORMAT_XRGB555 PIXEL_FORMAT_X1R5G5B5 -#define PIXEL_FORMAT_RGB555 PIXEL_FORMAT_X1R5G5B5 -#define PIXEL_FORMAT_RGB15 PIXEL_FORMAT_X1R5G5B5 +#define PIXEL_FORMAT_X1R5G5B5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 5, 5) +#define PIXEL_FORMAT_XRGB555 PIXEL_FORMAT_X1R5G5B5 +#define PIXEL_FORMAT_RGB555 PIXEL_FORMAT_X1R5G5B5 +#define PIXEL_FORMAT_RGB15 PIXEL_FORMAT_X1R5G5B5 -#define PIXEL_FORMAT_A1B5G5R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 1, 5, 5, 5) -#define PIXEL_FORMAT_ABGR555 PIXEL_FORMAT_A1B5G5R5 -#define PIXEL_FORMAT_ABGR15 PIXEL_FORMAT_A1B5G5R5 +#define PIXEL_FORMAT_A1B5G5R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 1, 5, 5, 5) +#define PIXEL_FORMAT_ABGR555 PIXEL_FORMAT_A1B5G5R5 +#define PIXEL_FORMAT_ABGR15 PIXEL_FORMAT_A1B5G5R5 -#define PIXEL_FORMAT_X1B5G5R5 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 5, 5) -#define PIXEL_FORMAT_XBGR555 PIXEL_FORMAT_X1B5G5R5 -#define PIXEL_FORMAT_BGR555 PIXEL_FORMAT_X1B5G5R5 -#define PIXEL_FORMAT_BGR15 PIXEL_FORMAT_X1B5G5R5 +#define PIXEL_FORMAT_X1B5G5R5 FREERDP_PIXEL_FORMAT(0, 16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 5, 5) +#define PIXEL_FORMAT_XBGR555 PIXEL_FORMAT_X1B5G5R5 +#define PIXEL_FORMAT_BGR555 PIXEL_FORMAT_X1B5G5R5 +#define PIXEL_FORMAT_BGR15 PIXEL_FORMAT_X1B5G5R5 /* 8bpp formats */ -#define PIXEL_FORMAT_A8 FREERDP_PIXEL_FORMAT(8, FREERDP_PIXEL_FORMAT_TYPE_A, 8, 0, 0, 0) -#define PIXEL_FORMAT_8BPP PIXEL_FORMAT_A8 -#define PIXEL_FORMAT_256 PIXEL_FORMAT_A8 +#define PIXEL_FORMAT_A8 FREERDP_PIXEL_FORMAT(0, 8, FREERDP_PIXEL_FORMAT_TYPE_A, 8, 0, 0, 0) +#define PIXEL_FORMAT_8BPP PIXEL_FORMAT_A8 +#define PIXEL_FORMAT_256 PIXEL_FORMAT_A8 /* 4 bpp formats */ -#define PIXEL_FORMAT_A4 FREERDP_PIXEL_FORMAT(4, FREERDP_PIXEL_FORMAT_TYPE_A, 4, 0, 0, 0) -#define PIXEL_FORMAT_4BPP PIXEL_FORMAT_A4 +#define PIXEL_FORMAT_A4 FREERDP_PIXEL_FORMAT(0, 4, FREERDP_PIXEL_FORMAT_TYPE_A, 4, 0, 0, 0) +#define PIXEL_FORMAT_4BPP PIXEL_FORMAT_A4 /* 1bpp formats */ -#define PIXEL_FORMAT_A1 FREERDP_PIXEL_FORMAT(1, FREERDP_PIXEL_FORMAT_TYPE_A, 1, 0, 0, 0) -#define PIXEL_FORMAT_1BPP PIXEL_FORMAT_A1 -#define PIXEL_FORMAT_MONO PIXEL_FORMAT_A1 +#define PIXEL_FORMAT_A1 FREERDP_PIXEL_FORMAT(0, 1, FREERDP_PIXEL_FORMAT_TYPE_A, 1, 0, 0, 0) +#define PIXEL_FORMAT_1BPP PIXEL_FORMAT_A1 +#define PIXEL_FORMAT_MONO PIXEL_FORMAT_A1 #ifdef __cplusplus extern "C" { @@ -372,6 +398,8 @@ FREERDP_API void freerdp_clrconv_free(HCLRCONV clrconv); FREERDP_API int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc); +FREERDP_API int freerdp_image_fill(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, + int nWidth, int nHeight, UINT32 color); #ifdef __cplusplus } diff --git a/include/freerdp/codec/zgfx.h b/include/freerdp/codec/zgfx.h new file mode 100644 index 000000000..6fd35825a --- /dev/null +++ b/include/freerdp/codec/zgfx.h @@ -0,0 +1,69 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * ZGFX (RDP8) Bulk Data Compression + * + * Copyright 2014 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_CODEC_ZGFX_H +#define FREERDP_CODEC_ZGFX_H + +#include +#include + +#include + +#define ZGFX_SEGMENTED_SINGLE 0xE0 +#define ZGFX_SEGMENTED_MULTIPART 0xE1 + +struct _ZGFX_CONTEXT +{ + BOOL Compressor; + + BYTE* pbInputCurrent; + BYTE* pbInputEnd; + + UINT32 bits; + UINT32 cBitsRemaining; + UINT32 BitsCurrent; + UINT32 cBitsCurrent; + + BYTE OutputBuffer[65536]; + UINT32 OutputCount; + + BYTE HistoryBuffer[2500000]; + UINT32 HistoryIndex; + UINT32 HistoryBufferSize; +}; +typedef struct _ZGFX_CONTEXT ZGFX_CONTEXT; + +#ifdef __cplusplus +extern "C" { +#endif + +FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags); +FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags); + +FREERDP_API void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush); + +FREERDP_API ZGFX_CONTEXT* zgfx_context_new(BOOL Compressor); +FREERDP_API void zgfx_context_free(ZGFX_CONTEXT* zgfx); + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_CODEC_ZGFX_H */ + diff --git a/include/freerdp/dvc.h b/include/freerdp/dvc.h index 7911fa556..ce5977541 100644 --- a/include/freerdp/dvc.h +++ b/include/freerdp/dvc.h @@ -137,11 +137,11 @@ struct _IWTSListenerCallback struct _IWTSVirtualChannelCallback { /* Notifies the user about data that is being received. */ - int (*OnDataReceived)(IWTSVirtualChannelCallback *pChannelCallback, - UINT32 cbSize, - BYTE *pBuffer); + int (*OnDataReceived) (IWTSVirtualChannelCallback* pChannelCallback, wStream* data); + /* Notifies the user that the channel has been opened. */ + int (*OnOpen) (IWTSVirtualChannelCallback* pChannelCallback); /* Notifies the user that the channel has been closed. */ - int (*OnClose)(IWTSVirtualChannelCallback *pChannelCallback); + int (*OnClose) (IWTSVirtualChannelCallback* pChannelCallback); }; /* The DVC Plugin entry points */ diff --git a/include/freerdp/utils/svc_plugin.h b/include/freerdp/utils/svc_plugin.h index e4fff81be..82d55225a 100644 --- a/include/freerdp/utils/svc_plugin.h +++ b/include/freerdp/utils/svc_plugin.h @@ -55,6 +55,7 @@ struct rdp_svc_plugin void* InitHandle; DWORD OpenHandle; wMessagePipe* MsgPipe; + wStreamPool *pool; }; #ifdef __cplusplus @@ -62,6 +63,8 @@ extern "C" { #endif FREERDP_API void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints); +FREERDP_API void svc_plugin_terminate(rdpSvcPlugin* plugin); + FREERDP_API int svc_plugin_send(rdpSvcPlugin* plugin, wStream* data_out); FREERDP_API int svc_plugin_send_event(rdpSvcPlugin* plugin, wMessage* event); diff --git a/libfreerdp/codec/CMakeLists.txt b/libfreerdp/codec/CMakeLists.txt index f0ba7f746..ad0180e25 100644 --- a/libfreerdp/codec/CMakeLists.txt +++ b/libfreerdp/codec/CMakeLists.txt @@ -50,6 +50,8 @@ set(${MODULE_PREFIX}_SRCS ncrush.c xcrush.c mppc.c + zgfx.c + clear.c jpeg.c) set(${MODULE_PREFIX}_SSE2_SRCS diff --git a/libfreerdp/codec/bitmap_decode.c b/libfreerdp/codec/bitmap_decode.c index 2330872c9..c5232d988 100644 --- a/libfreerdp/codec/bitmap_decode.c +++ b/libfreerdp/codec/bitmap_decode.c @@ -260,7 +260,9 @@ static UINT32 ExtractRunLength(UINT32 code, BYTE* pbOrderHdr, UINT32* advance) */ BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp) { - BYTE* TmpBfr; + int status; + BYTE* TmpBfr; + BYTE* pDstData; if (srcBpp == 16 && dstBpp == 16) { @@ -271,7 +273,12 @@ BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int } else if (srcBpp == 32 && dstBpp == 32) { - if (freerdp_bitmap_planar_decompress(srcData, dstData, width, height, size) < 0) + pDstData = dstData; + + status = planar_decompress(NULL, srcData, size, &pDstData, + PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height); + + if (status < 0) return FALSE; } else if (srcBpp == 15 && dstBpp == 15) diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c new file mode 100644 index 000000000..c57f8c641 --- /dev/null +++ b/libfreerdp/codec/clear.c @@ -0,0 +1,340 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * ClearCodec Bitmap Compression + * + * Copyright 2014 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 + +int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize) +{ + int index; + BYTE glyphFlags; + BYTE seqNumber; + UINT16 glyphIndex; + UINT32 offset = 0; + UINT32 residualByteCount; + UINT32 bandsByteCount; + UINT32 subcodecByteCount; + + if (SrcSize < 2) + return -1001; + + glyphFlags = pSrcData[0]; + seqNumber = pSrcData[1]; + offset += 2; + + printf("glyphFlags: 0x%02X seqNumber: %d\n", glyphFlags, seqNumber); + + if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX) + { + if (SrcSize < 4) + return -1002; + + glyphIndex = *((UINT16*) &pSrcData[2]); + offset += 2; + + if (glyphFlags & CLEARCODEC_FLAG_GLYPH_HIT) + { + /** + * Copy pixels from the Decompressor Glyph Storage position + * specified by the glyphIndex field to the output bitmap + */ + + return 1; /* Finish */ + } + } + + /* Read composition payload header parameters */ + + if ((SrcSize - offset) < 12) + return -1003; + + residualByteCount = *((UINT32*) &pSrcData[offset]); + bandsByteCount = *((UINT32*) &pSrcData[offset + 4]); + subcodecByteCount = *((UINT32*) &pSrcData[offset + 8]); + offset += 12; + + printf("residualByteCount: %d bandsByteCount: %d subcodecByteCount: %d\n", + residualByteCount, bandsByteCount, subcodecByteCount); + + if (residualByteCount > 0) + { + BYTE blueValue; + BYTE greenValue; + BYTE redValue; + UINT32 suboffset; + BYTE* residualData; + BYTE runLengthFactor1 = 0; + UINT16 runLengthFactor2 = 0; + UINT32 runLengthFactor3 = 0; + UINT32 runLengthFactor = 0; + + if ((SrcSize - offset) < residualByteCount) + return -1004; + + suboffset = 0; + residualData = &pSrcData[offset]; + + while (suboffset < residualByteCount) + { + if ((residualByteCount - suboffset) < 4) + return -1005; + + blueValue = residualData[suboffset]; + greenValue = residualData[suboffset + 1]; + redValue = residualData[suboffset + 2]; + suboffset += 3; + + runLengthFactor1 = residualData[suboffset]; + runLengthFactor = runLengthFactor1; + suboffset += 1; + + if (runLengthFactor1 >= 0xFF) + { + if ((residualByteCount - suboffset) < 2) + return -1006; + + runLengthFactor2 = *((UINT16*) &residualData[suboffset]); + runLengthFactor = runLengthFactor2; + suboffset += 2; + + if (runLengthFactor2 >= 0xFFFF) + { + if ((residualByteCount - suboffset) < 4) + return -1007; + + runLengthFactor3 = *((UINT32*) &residualData[suboffset]); + runLengthFactor = runLengthFactor3; + suboffset += 4; + } + } + } + + /* Decompress residual layer and write to output bitmap */ + offset += residualByteCount; + } + + if (bandsByteCount > 0) + { + BYTE* bandsData; + UINT32 suboffset; + + if ((SrcSize - offset) < bandsByteCount) + return -1008; + + suboffset = 0; + bandsData = &pSrcData[offset]; + + while (suboffset < bandsByteCount) + { + UINT16 xStart; + UINT16 xEnd; + UINT16 yStart; + UINT16 yEnd; + BYTE blueBkg; + BYTE greenBkg; + BYTE redBkg; + BYTE* vBars; + UINT16 vBarHeader; + UINT16 vBarIndex; + UINT16 vBarYOn; + UINT16 vBarYOff; + int vBarCount; + int vBarPixelCount; + + if ((bandsByteCount - suboffset) < 11) + return -1009; + + xStart = *((UINT16*) &bandsData[suboffset]); + xEnd = *((UINT16*) &bandsData[suboffset + 2]); + yStart = *((UINT16*) &bandsData[suboffset + 4]); + yEnd = *((UINT16*) &bandsData[suboffset + 6]); + blueBkg = bandsData[suboffset + 8]; + greenBkg = bandsData[suboffset + 9]; + redBkg = bandsData[suboffset + 10]; + suboffset += 11; + + vBarCount = (xEnd - xStart) + 1; + + printf("CLEARCODEC_BAND: xStart: %d xEnd: %d yStart: %d yEnd: %d vBarCount: %d blueBkg: 0x%02X greenBkg: 0x%02X redBkg: 0x%02X\n", + xStart, xEnd, yStart, yEnd, vBarCount, blueBkg, greenBkg, redBkg); + + for (index = 0; index < vBarCount; index++) + { + vBars = &bandsData[suboffset]; + + if ((bandsByteCount - suboffset) < 2) + return -1010; + + vBarHeader = *((UINT16*) &vBars[0]); + suboffset += 2; + + if ((vBarHeader & 0xC000) == 0x8000) /* VBAR_CACHE_HIT */ + { + vBarIndex = (vBarHeader & 0x7FFF); + + printf("VBAR_CACHE_HIT: vBarIndex: %d\n", + vBarIndex); + } + else if ((vBarHeader & 0xC000) == 0xC000) /* SHORT_VBAR_CACHE_HIT */ + { + vBarIndex = (vBarHeader & 0x3FFF); + + if ((bandsByteCount - suboffset) < 1) + return -1011; + + vBarYOn = vBars[2]; + suboffset += 1; + + printf("SHORT_VBAR_CACHE_HIT: vBarIndex: %d vBarYOn: %d\n", + vBarIndex, vBarYOn); + } + else if ((vBarHeader & 0xC000) == 0x0000) /* SHORT_VBAR_CACHE_MISS */ + { + vBarYOn = (vBarHeader & 0xFF); + vBarYOff = ((vBarHeader >> 8) & 0x3F); + + if (vBarYOff < vBarYOn) + return -1012; + + /* shortVBarPixels: variable */ + + vBarPixelCount = (3 * (vBarYOff - vBarYOn)); + + printf("SHORT_VBAR_CACHE_MISS: vBarYOn: %d vBarYOff: %d bytes: %d\n", + vBarYOn, vBarYOff, vBarPixelCount); + + if ((bandsByteCount - suboffset) < vBarPixelCount) + return -1013; + + suboffset += vBarPixelCount; + } + else + { + return -1014; /* invalid vBarHeader */ + } + } + } + + /* Decompress bands layer and write to output bitmap */ + offset += bandsByteCount; + } + + if (subcodecByteCount > 0) + { + UINT16 xStart; + UINT16 yStart; + UINT16 width; + UINT16 height; + BYTE* bitmapData; + UINT32 bitmapDataByteCount; + BYTE subcodecId; + BYTE* subcodecs; + UINT32 suboffset; + + if ((SrcSize - offset) < subcodecByteCount) + return -1015; + + suboffset = 0; + subcodecs = &pSrcData[offset]; + + while (suboffset < subcodecByteCount) + { + if ((subcodecByteCount - suboffset) < 13) + return -1016; + + xStart = *((UINT16*) &subcodecs[suboffset]); + yStart = *((UINT16*) &subcodecs[suboffset + 2]); + width = *((UINT16*) &subcodecs[suboffset + 4]); + height = *((UINT16*) &subcodecs[suboffset + 6]); + bitmapDataByteCount = *((UINT32*) &subcodecs[suboffset + 8]); + subcodecId = subcodecs[suboffset + 12]; + suboffset += 13; + + printf("bitmapDataByteCount: %d subcodecByteCount: %d suboffset: %d subCodecId: %d\n", + bitmapDataByteCount, subcodecByteCount, suboffset, subcodecId); + + if ((subcodecByteCount - suboffset) < bitmapDataByteCount) + return -1017; + + bitmapData = &subcodecs[suboffset]; + + suboffset += bitmapDataByteCount; + } + + /* Decompress subcodec layer and write to output bitmap */ + offset += subcodecByteCount; + } + + if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX) + { + /** + * Copy decompressed bitmap to the Decompressor Glyph + * Storage position specified by the glyphIndex field + */ + } + + if (offset != SrcSize) + { + printf("clear_decompress: incomplete processing of bytes: Actual: %d, Expected: %d\n", offset, SrcSize); + } + + return 1; +} + +int clear_compress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize) +{ + return 1; +} + +void clear_context_reset(CLEAR_CONTEXT* clear) +{ + +} + +CLEAR_CONTEXT* clear_context_new(BOOL Compressor) +{ + CLEAR_CONTEXT* clear; + + clear = (CLEAR_CONTEXT*) calloc(1, sizeof(CLEAR_CONTEXT)); + + if (clear) + { + clear->Compressor = Compressor; + + clear_context_reset(clear); + } + + return clear; +} + +void clear_context_free(CLEAR_CONTEXT* clear) +{ + if (clear) + { + free(clear); + } +} + diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index 69a871c84..540d31331 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -1175,18 +1175,34 @@ void freerdp_clrconv_free(HCLRCONV clrconv) int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BYTE* pSrcData, DWORD dwSrcFormat, int nSrcStep, int nXSrc, int nYSrc) { - int i, j; + int x, y; + int srcFlip; + int dstFlip; BYTE a, r, g, b; + int beg, end, inc; int srcBitsPerPixel; int srcBytesPerPixel; int dstBitsPerPixel; int dstBytesPerPixel; + BOOL overlap = FALSE; + BOOL vFlip = FALSE; srcBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwSrcFormat); srcBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwSrcFormat) / 8); + srcFlip = FREERDP_PIXEL_FORMAT_FLIP(dwSrcFormat); dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwDstFormat); dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwDstFormat) / 8); + dstFlip = FREERDP_PIXEL_FORMAT_FLIP(dwDstFormat); + + if (srcFlip != dstFlip) + vFlip = TRUE; + + if (pDstData == pSrcData) + { + overlap = (((nXDst + nWidth) > nXSrc) && (nXDst < (nXSrc + nWidth)) && + ((nYDst + nHeight) > nYSrc) && (nYDst < (nYSrc + nHeight))) ? TRUE : FALSE; + } if (srcBytesPerPixel == 4) { @@ -1195,7 +1211,7 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs if (srcBitsPerPixel == 24) { - if (dstBytesPerPixel == 4) + if (dstBytesPerPixel == 4) /* srcBytesPerPixel == dstBytesPerPixel */ { if (dstBitsPerPixel == 32) { @@ -1208,9 +1224,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; - for (i = 0; i < nHeight; i++) + for (y = 0; y < nHeight; y++) { - for (j = 0; j < nWidth; j++) + for (x = 0; x < nWidth; x++) { GetARGB32(a, r, g, b, *pSrcPixel); *pDstPixel = ARGB32(a, r, g, b); @@ -1223,7 +1239,7 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))]; } } - else if (dstBitsPerPixel == 24) + else if (dstBitsPerPixel == 24) /* srcBitsPerPixel == dstBitsPerPixel */ { UINT32* pSrcPixel; UINT32* pDstPixel; @@ -1231,22 +1247,36 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs if (nDstStep < 0) nDstStep = dstBytesPerPixel * nWidth; - pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; - pDstPixel = (UINT32*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; - - for (i = 0; i < nHeight; i++) + if (overlap && (nYSrc < nYDst)) { - for (j = 0; j < nWidth; j++) + beg = nHeight - 1; + inc = -1; /* downward copy */ + end = -1; + } + else + { + beg = 0; + inc = 1; /* upward copy */ + end = nHeight; + } + + if (!vFlip) + { + for (y = beg; y != end; y += inc) { - GetRGB32(r, g, b, *pSrcPixel); - *pDstPixel = RGB32(r, g, b); - - pSrcPixel++; - pDstPixel++; + pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * srcBytesPerPixel)]; + pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * dstBytesPerPixel)]; + MoveMemory(pDstPixel, pSrcPixel, nWidth * 4); + } + } + else + { + for (y = beg; y != end; y += inc) + { + pSrcPixel = (UINT32*) &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * srcBytesPerPixel)]; + pDstPixel = (UINT32*) &pDstData[((nYDst + (nHeight - y - 1)) * nDstStep) + (nXDst * dstBytesPerPixel)]; + MoveMemory(pDstPixel, pSrcPixel, nWidth * 4); } - - pSrcPixel = (UINT32*) &((BYTE*) pSrcPixel)[(nSrcStep - (nWidth * srcBytesPerPixel))]; - pDstPixel = (UINT32*) &((BYTE*) pDstPixel)[(nDstStep - (nWidth * dstBytesPerPixel))]; } } } @@ -1261,9 +1291,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; pDstPixel = (BYTE*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; - for (i = 0; i < nHeight; i++) + for (y = 0; y < nHeight; y++) { - for (j = 0; j < nWidth; j++) + for (x = 0; x < nWidth; x++) { GetRGB32(r, g, b, *pSrcPixel); @@ -1291,9 +1321,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; - for (i = 0; i < nHeight; i++) + for (y = 0; y < nHeight; y++) { - for (j = 0; j < nWidth; j++) + for (x = 0; x < nWidth; x++) { GetRGB32(r, g, b, *pSrcPixel); RGB_888_565(r, g, b); @@ -1318,9 +1348,9 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs pSrcPixel = (UINT32*) &pSrcData[(nYSrc * nSrcStep) + (nXSrc * srcBytesPerPixel)]; pDstPixel = (UINT16*) &pDstData[(nYDst * nDstStep) + (nXDst * dstBytesPerPixel)]; - for (i = 0; i < nHeight; i++) + for (y = 0; y < nHeight; y++) { - for (j = 0; j < nWidth; j++) + for (x = 0; x < nWidth; x++) { GetRGB32(r, g, b, *pSrcPixel); RGB_888_555(r, g, b); @@ -1340,3 +1370,56 @@ int freerdp_image_copy(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDs return 0; } + +void* freerdp_image_memset32(UINT32* ptr, UINT32 fill, size_t length) +{ + while (length--) + { + *ptr++ = fill; + } + + return (void*) ptr; +} + +int freerdp_image_fill(BYTE* pDstData, DWORD dwDstFormat, int nDstStep, int nXDst, int nYDst, + int nWidth, int nHeight, UINT32 color) +{ + int y; + int dstBitsPerPixel; + int dstBytesPerPixel; + + dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(dwDstFormat); + dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(dwDstFormat) / 8); + + if (dstBytesPerPixel == 4) + { + UINT32* pDstPixel; + + if (nDstStep < 0) + nDstStep = dstBytesPerPixel * nWidth; + + for (y = 0; y < nHeight; y++) + { + pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * dstBytesPerPixel)]; + freerdp_image_memset32(pDstPixel, color, nWidth); + } + } + else if (dstBytesPerPixel == 3) + { + + } + else if (dstBytesPerPixel == 2) + { + if (dstBitsPerPixel == 16) + { + + } + else if (dstBitsPerPixel == 15) + { + + } + } + + return 0; +} + diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index a320da5a3..824376ffb 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -28,54 +28,59 @@ #include "planar.h" -static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int srcSize) +static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, + int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel, BOOL vFlip) { - int k; int x, y; BYTE* srcp; BYTE* dstp; UINT32 pixel; - int scanline; int cRawBytes; int nRunLength; int deltaValue; + int beg, end, inc; BYTE controlByte; BYTE* currentScanline; BYTE* previousScanline; - k = 0; - - srcp = inPlane; - dstp = outPlane; - scanline = width * 4; + srcp = pSrcData; + dstp = pDstData; previousScanline = NULL; - y = 0; - - while (y < height) + if (vFlip) { + beg = nHeight - 1; + end = -1; + inc = -1; + } + else + { + beg = 0; + end = nHeight; + inc = 1; + } + + for (y = beg; y != end; y += inc) + { + dstp = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4) + nChannel]; + pixel = 0; - dstp = (outPlane + height * scanline) - ((y + 1) * scanline); currentScanline = dstp; - x = 0; - - while (x < width) + for (x = 0; x < nWidth; ) { controlByte = *srcp; srcp++; - if ((srcp - inPlane) > srcSize) + if ((srcp - pSrcData) > SrcSize) { - printf("freerdp_bitmap_planar_decompress_plane_rle: error reading input buffer\n"); + fprintf(stderr, "planar_decompress_plane_rle: error reading input buffer\n"); return -1; } nRunLength = PLANAR_CONTROL_BYTE_RUN_LENGTH(controlByte); cRawBytes = PLANAR_CONTROL_BYTE_RAW_BYTES(controlByte); - //printf("CONTROL(%d, %d)\n", cRawBytes, nRunLength); - if (nRunLength == 1) { nRunLength = cRawBytes + 16; @@ -87,23 +92,9 @@ static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, cRawBytes = 0; } -#if 0 - printf("y: %d cRawBytes: %d nRunLength: %d\n", y, cRawBytes, nRunLength); - - printf("RAW["); - - for (k = 0; k < cRawBytes; k++) + if (((dstp + (cRawBytes + nRunLength)) - currentScanline) > nWidth * 4) { - printf("0x%02X%s", srcp[k], - ((k + 1) == cRawBytes) ? "" : ", "); - } - - printf("] RUN[%d]\n", nRunLength); -#endif - - if (((dstp + (cRawBytes + nRunLength)) - currentScanline) > width * 4) - { - printf("freerdp_bitmap_planar_decompress_plane_rle: too many pixels in scanline\n"); + fprintf(stderr, "planar_decompress_plane_rle: too many pixels in scanline\n"); return -1; } @@ -170,34 +161,76 @@ static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, } previousScanline = currentScanline; - y++; } - return (int) (srcp - inPlane); + return (int) (srcp - pSrcData); } -static int freerdp_bitmap_planar_decompress_plane_raw(BYTE* srcData, int width, int height, BYTE* dstData, int size) +static int planar_decompress_plane_raw(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, + int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel, BOOL vFlip) { int x, y; + int beg, end, inc; + BYTE* dstp = NULL; + BYTE* srcp = pSrcData; - for (y = 0; y < height; y++) + if (vFlip) { - for (x = 0; x < width; x++) + beg = nHeight - 1; + end = -1; + inc = -1; + } + else + { + beg = 0; + end = nHeight; + inc = 1; + } + + for (y = beg; y != end; y += inc) + { + dstp = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4) + nChannel]; + + for (x = 0; x < nWidth; x++) { - dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)]; + *dstp = *srcp; + dstp += 4; + srcp++; } } - return (width * height); + return (int) (srcp - pSrcData); } -int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size) +int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize, + BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) { + int status; BYTE* srcp; - int dstSize; + BOOL vFlip; BYTE FormatHeader; + BYTE* pDstData = NULL; + UINT32 UncompressedSize; - srcp = srcData; + if ((nWidth * nHeight) <= 0) + return -1; + + vFlip = FREERDP_PIXEL_FORMAT_FLIP(DstFormat) ? TRUE : FALSE; + + srcp = pSrcData; + UncompressedSize = nWidth * nHeight * 4; + + pDstData = *ppDstData; + + if (!pDstData) + { + pDstData = (BYTE*) malloc(UncompressedSize); + + if (!pDstData) + return -1; + + *ppDstData = pDstData; + } FormatHeader = *srcp; srcp++; @@ -208,17 +241,23 @@ int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, in { if (FormatHeader & PLANAR_FORMAT_HEADER_RLE) { - dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 3, size - (srcp - srcData)); + status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3, vFlip); - if (dstSize < 0) + if (status < 0) return -1; - srcp += dstSize; + srcp += status; } else { - dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 3, size - (srcp - srcData)); - srcp += dstSize; + status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3, vFlip); + + if (status < 0) + return -1; + + srcp += status; } } @@ -226,51 +265,71 @@ int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, in { /* LumaOrRedPlane */ - dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 2, size - (srcp - srcData)); + status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip); - if (dstSize < 0) + if (status < 0) return -1; - srcp += dstSize; + srcp += status; /* OrangeChromaOrGreenPlane */ - dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 1, size - (srcp - srcData)); + status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip); - if (dstSize < 0) + if (status < 0) return -1; - srcp += dstSize; + srcp += status; /* GreenChromeOrBluePlane */ - dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 0, size - (srcp - srcData)); + status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData), + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip); - if (dstSize < 0) + if (status < 0) return -1; - srcp += dstSize; + srcp += status; } else { /* LumaOrRedPlane */ - dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 2, size - (srcp - srcData)); - srcp += dstSize; + status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip); + + if (status < 0) + return -1; + + srcp += status; /* OrangeChromaOrGreenPlane */ - dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 1, size - (srcp - srcData)); - srcp += dstSize; + status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip); + + if (status < 0) + return -1; + + srcp += status; /* GreenChromeOrBluePlane */ - dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 0, size - (srcp - srcData)); - srcp += dstSize; + status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData), + pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip); + + if (status < 0) + return -1; + + srcp += status; srcp++; } - return (size == (srcp - srcData)) ? 0 : -1; + status = (SrcSize == (srcp - pSrcData)) ? 1 : -1; + + return status; } int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4]) diff --git a/libfreerdp/codec/planar.h b/libfreerdp/codec/planar.h index bbb9f6068..a8e34c87a 100644 --- a/libfreerdp/codec/planar.h +++ b/libfreerdp/codec/planar.h @@ -87,8 +87,6 @@ struct _BITMAP_PLANAR_CONTEXT BYTE* rlePlanesBuffer; }; -FREERDP_API int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size); - FREERDP_API int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4]); FREERDP_API BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* plane, int width, int height, BYTE* outPlane, int* dstSize); FREERDP_API BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane); diff --git a/libfreerdp/codec/region.c b/libfreerdp/codec/region.c index aee2e3036..b8a24e136 100644 --- a/libfreerdp/codec/region.c +++ b/libfreerdp/codec/region.c @@ -107,13 +107,14 @@ const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRects) static INLINE RECTANGLE_16 *region16_rects_noconst(REGION16 *region) { - REGION16_DATA *data; + REGION16_DATA* data; data = region->data; - if (!data) - return 0; - return (RECTANGLE_16 *)(data + 1); + if (!data) + return NULL; + + return (RECTANGLE_16*)(&data[1]); } const RECTANGLE_16 *region16_extents(const REGION16 *region) @@ -158,20 +159,24 @@ void region16_clear(REGION16 *region) if (region->data->size) free(region->data); + region->data = &empty_region; ZeroMemory(®ion->extents, sizeof(region->extents)); } -static INLINE REGION16_DATA *allocateRegion(long nbItems) +static INLINE REGION16_DATA* allocateRegion(long nbItems) { - long allocSize = sizeof(REGION16_DATA) + nbItems * sizeof(RECTANGLE_16); - REGION16_DATA *ret = (REGION16_DATA *)malloc(allocSize); + long allocSize = sizeof(REGION16_DATA) + (nbItems * sizeof(RECTANGLE_16)); + + REGION16_DATA* ret = (REGION16_DATA*) malloc(allocSize); + if (!ret) return ret; ret->size = allocSize; ret->nbRects = nbItems; + return ret; } @@ -186,6 +191,7 @@ BOOL region16_copy(REGION16 *dst, const REGION16 *src) return TRUE; dst->extents = src->extents; + if (dst->data->size) free(dst->data); @@ -196,11 +202,13 @@ BOOL region16_copy(REGION16 *dst, const REGION16 *src) else { dst->data = allocateRegion(src->data->nbRects); + if (!dst->data) return FALSE; - memcpy(dst->data, src->data, src->data->size); + CopyMemory(dst->data, src->data, src->data->size); } + return TRUE; } @@ -310,29 +318,34 @@ void region16_copy_band_with_union(RECTANGLE_16 *dst, src++; dst++; *dstCounter += 1; } - if(srcPtr) + if (srcPtr) *srcPtr = src; + *dstPtr = dst; } -static RECTANGLE_16 *next_band(RECTANGLE_16 *band1, RECTANGLE_16 *endPtr, int *nbItems) +static RECTANGLE_16* next_band(RECTANGLE_16* band1, RECTANGLE_16* endPtr, int* nbItems) { UINT16 refY = band1->top; *nbItems = 0; - while((band1 < endPtr) && (band1->top == refY)) { + + while((band1 < endPtr) && (band1->top == refY)) + { band1++; *nbItems += 1; } + return band1; } -static BOOL band_match(const RECTANGLE_16 *band1, const RECTANGLE_16 *band2, RECTANGLE_16 *endPtr) +static BOOL band_match(const RECTANGLE_16* band1, const RECTANGLE_16* band2, RECTANGLE_16* endPtr) { int refBand2 = band2->top; - const RECTANGLE_16 *band2Start = band2; + const RECTANGLE_16* band2Start = band2; - while ((band1 < band2Start) && (band2 < endPtr) && (band2->top == refBand2)) { + while ((band1 < band2Start) && (band2 < endPtr) && (band2->top == refBand2)) + { if ((band1->left != band2->left) || (band1->right != band2->right)) return FALSE; @@ -391,14 +404,17 @@ BOOL region16_simplify_bands(REGION16 *region) int bandItems, toMove; finalNbRects = nbRects = region16_n_rects(region); + if (nbRects < 2) return TRUE; band1 = region16_rects_noconst(region); endPtr = band1 + nbRects; - do { + do + { band2 = next_band(band1, endPtr, &bandItems); + if (band2 == endPtr) break; @@ -416,38 +432,45 @@ BOOL region16_simplify_bands(REGION16 *region) * may be merged too */ endBand = band2 + bandItems; toMove = (endPtr - endBand) * sizeof(RECTANGLE_16); + if (toMove) - memmove(band2, endBand, toMove); + MoveMemory(band2, endBand, toMove); + finalNbRects -= bandItems; endPtr -= bandItems; - } else { + } + else + { band1 = band2; } - } while(TRUE); + } + while(TRUE); if (finalNbRects != nbRects) { - int allocSize = sizeof(REGION16_DATA) + finalNbRects * sizeof(RECTANGLE_16); + int allocSize = sizeof(REGION16_DATA) + (finalNbRects * sizeof(RECTANGLE_16)); region->data = realloc(region->data, allocSize); + if (!region->data) { region->data = &empty_region; return FALSE; } + region->data->nbRects = finalNbRects; region->data->size = allocSize; } + return TRUE; } - BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 *rect) { - const RECTANGLE_16 *srcExtents; - RECTANGLE_16 *dstExtents; + const RECTANGLE_16* srcExtents; + RECTANGLE_16* dstExtents; const RECTANGLE_16 *currentBand, *endSrcRect, *nextBand; - REGION16_DATA *newItems; - RECTANGLE_16 *dstRect; + REGION16_DATA* newItems = NULL; + RECTANGLE_16* dstRect = NULL; int usedRects, srcNbRects; UINT16 topInterBand; @@ -463,19 +486,26 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 /* source is empty, so the union is rect */ dst->extents = *rect; dst->data = allocateRegion(1); + if (!dst->data) return FALSE; dstRect = region16_rects_noconst(dst); - *dstRect = *rect; + + dstRect->top = rect->top; + dstRect->left = rect->left; + dstRect->right = rect->right; + dstRect->bottom = rect->bottom; + return TRUE; } - newItems = allocateRegion((1 + region16_n_rects(src)) * 2); + newItems = allocateRegion((1 + region16_n_rects(src)) * 4); + if (!newItems) return FALSE; - dstRect = (RECTANGLE_16 *)(newItems + 1); + dstRect = (RECTANGLE_16*) (&newItems[1]); usedRects = 0; /* adds the piece of rect that is on the top of src */ @@ -497,8 +527,7 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 while (currentBand < endSrcRect) { if ((currentBand->bottom <= rect->top) || (rect->bottom <= currentBand->top) || - rectangle_contained_in_band(currentBand, endSrcRect, rect) - ) + rectangle_contained_in_band(currentBand, endSrcRect, rect)) { /* no overlap between rect and the band, rect is totally below or totally above * the current band, or rect is already covered by an item of the band. @@ -560,9 +589,10 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 mergeTop = rect->top; } - /* do the merge zone (all cases ) */ + /* do the merge zone (all cases) */ if (rect->bottom < currentBand->bottom) mergeBottom = rect->bottom; + region16_copy_band_with_union(dstRect, currentBand, endSrcRect, mergeTop, mergeBottom, @@ -629,19 +659,20 @@ BOOL region16_union_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE_16 dstExtents->bottom = MAX(rect->bottom, srcExtents->bottom); dstExtents->right = MAX(rect->right, srcExtents->right); - newItems->size = sizeof(REGION16_DATA) + usedRects * sizeof(RECTANGLE_16); + newItems->size = sizeof(REGION16_DATA) + (usedRects * sizeof(RECTANGLE_16)); dst->data = realloc(newItems, newItems->size); + if (!dst->data) { free(newItems); return FALSE; } + dst->data->nbRects = usedRects; return region16_simplify_bands(dst); } - BOOL region16_intersects_rect(const REGION16 *src, const RECTANGLE_16 *arg2) { const RECTANGLE_16 *rect, *endPtr, *srcExtents; @@ -651,10 +682,12 @@ BOOL region16_intersects_rect(const REGION16 *src, const RECTANGLE_16 *arg2) assert(src->data); rect = region16_rects(src, &nbRects); + if (!nbRects) return FALSE; srcExtents = region16_extents(src); + if (nbRects == 1) return rectangles_intersects(srcExtents, arg2); @@ -684,6 +717,7 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE assert(src->data); srcPtr = region16_rects(src, &nbRects); + if (!nbRects) { region16_clear(dst); @@ -691,27 +725,32 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE } srcExtents = region16_extents(src); + if (nbRects == 1) { BOOL intersects = rectangles_intersection(srcExtents, rect, &common); region16_clear(dst); + if (intersects) return region16_union_rect(dst, dst, &common); + return TRUE; } newItems = allocateRegion(nbRects); + if (!newItems) return FALSE; - dstPtr = (RECTANGLE_16 *)(newItems + 1); + + dstPtr = (RECTANGLE_16*) (&newItems[1]); usedRects = 0; ZeroMemory(&newExtents, sizeof(newExtents)); /* accumulate intersecting rectangles, the final region16_simplify_bands() will * do all the bad job to recreate correct rectangles */ - for(endPtr = srcPtr + nbRects; (srcPtr < endPtr) && (rect->bottom > srcPtr->top); srcPtr++) + for (endPtr = srcPtr + nbRects; (srcPtr < endPtr) && (rect->bottom > srcPtr->top); srcPtr++) { if (rectangles_intersection(srcPtr, rect, &common)) { @@ -727,13 +766,15 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE } newItems->nbRects = usedRects; - newItems->size = sizeof(REGION16_DATA) + usedRects * sizeof(RECTANGLE_16); + newItems->size = sizeof(REGION16_DATA) + (usedRects * sizeof(RECTANGLE_16)); if (dst->data->size) free(dst->data); dst->data = realloc(newItems, newItems->size); - if (!dst->data) { + + if (!dst->data) + { free(newItems); return FALSE; } @@ -742,15 +783,13 @@ BOOL region16_intersect_rect(REGION16 *dst, const REGION16 *src, const RECTANGLE return region16_simplify_bands(dst); } -void region16_uninit(REGION16 *region) { +void region16_uninit(REGION16 *region) +{ assert(region); assert(region->data); - if(region->data->size) + if (region->data->size) free(region->data); - region->data = 0; + + region->data = NULL; } - - - - diff --git a/libfreerdp/codec/test/CMakeLists.txt b/libfreerdp/codec/test/CMakeLists.txt index b63feac4c..ba158560c 100644 --- a/libfreerdp/codec/test/CMakeLists.txt +++ b/libfreerdp/codec/test/CMakeLists.txt @@ -9,7 +9,9 @@ set(${MODULE_PREFIX}_TESTS TestFreeRDPCodecMppc.c TestFreeRDPCodecNCrush.c TestFreeRDPCodecXCrush.c + TestFreeRDPCodecZGfx.c TestFreeRDPCodecPlanar.c + TestFreeRDPCodecClear.c TestFreeRDPCodecRemoteFX.c) create_test_sourcelist(${MODULE_PREFIX}_SRCS diff --git a/libfreerdp/codec/test/TestFreeRDPCodecClear.c b/libfreerdp/codec/test/TestFreeRDPCodecClear.c new file mode 100644 index 000000000..fcec61acf --- /dev/null +++ b/libfreerdp/codec/test/TestFreeRDPCodecClear.c @@ -0,0 +1,144 @@ +#include +#include + +#include + +static BYTE TEST_CLEAR_EXAMPLE_1[] = "\x03\xc3\x11\x00"; + +static BYTE TEST_CLEAR_EXAMPLE_2[] = + "\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x82\x00\x00\x00\x00\x00" + "\x00\x00\x4e\x00\x11\x00\x75\x00\x00\x00\x02\x0e\xff\xff\xff\x00" + "\x00\x00\xdb\xff\xff\x00\x3a\x90\xff\xb6\x66\x66\xb6\xff\xb6\x66" + "\x00\x90\xdb\xff\x00\x00\x3a\xdb\x90\x3a\x3a\x90\xdb\x66\x00\x00" + "\xff\xff\xb6\x64\x64\x64\x11\x04\x11\x4c\x11\x4c\x11\x4c\x11\x4c" + "\x11\x4c\x00\x47\x13\x00\x01\x01\x04\x00\x01\x00\x00\x47\x16\x00" + "\x11\x02\x00\x47\x29\x00\x11\x01\x00\x49\x0a\x00\x01\x00\x04\x00" + "\x01\x00\x00\x4a\x0a\x00\x09\x00\x01\x00\x00\x47\x05\x00\x01\x01" + "\x1c\x00\x01\x00\x11\x4c\x11\x4c\x11\x4c\x00\x47\x0d\x4d\x00\x4d"; + +static BYTE TEST_CLEAR_EXAMPLE_3[] = + "\x00\xdf\x0e\x00\x00\x00\x8b\x00\x00\x00\x00\x00\x00\x00\xfe\xfe" + "\xfe\xff\x80\x05\xff\xff\xff\x40\xfe\xfe\xfe\x40\x00\x00\x3f\x00" + "\x03\x00\x0b\x00\xfe\xfe\xfe\xc5\xd0\xc6\xd0\xc7\xd0\x68\xd4\x69" + "\xd4\x6a\xd4\x6b\xd4\x6c\xd4\x6d\xd4\x1a\xd4\x1a\xd4\xa6\xd0\x6e" + "\xd4\x6f\xd4\x70\xd4\x71\xd4\x72\xd4\x73\xd4\x74\xd4\x21\xd4\x22" + "\xd4\x23\xd4\x24\xd4\x25\xd4\xd9\xd0\xda\xd0\xdb\xd0\xc5\xd0\xc5" + "\xd0\xdc\xd0\xc2\xd0\x21\xd4\x22\xd4\x23\xd4\x24\xd4\x25\xd4\xc9" + "\xd0\xca\xd0\x5a\xd4\x2b\xd1\x28\xd1\x2c\xd1\x75\xd4\x27\xd4\x28" + "\xd4\x29\xd4\x2a\xd4\x1a\xd4\x1a\xd4\x1a\xd4\xb7\xd0\xb8\xd0\xb9" + "\xd0\xba\xd0\xbb\xd0\xbc\xd0\xbd\xd0\xbe\xd0\xbf\xd0\xc0\xd0\xc1" + "\xd0\xc2\xd0\xc3\xd0\xc4\xd0"; + +static BYTE TEST_CLEAR_EXAMPLE_4[] = + "\x01\x0b\x78\x00\x00\x00\x00\x00\x46\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x06\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x0f\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xb6\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xb6\x66\xff\xff\xff\xff\xff\xff\xff\xb6\x66\xdb\x90\x3a\xff\xff" + "\xb6\xff\xff\xff\xff\xff\xff\xff\xff\xff\x46\x91\x47\x91\x48\x91" + "\x49\x91\x4a\x91\x1b\x91"; + +int test_ClearDecompressExample1() +{ + int status; + BYTE* pSrcData; + UINT32 SrcSize; + UINT32 DstSize; + BYTE* pDstData = NULL; + CLEAR_CONTEXT* clear; + + clear = clear_context_new(FALSE); + + SrcSize = sizeof(TEST_CLEAR_EXAMPLE_1) - 1; + pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_1; + + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + + printf("clear_decompress example 1 status: %d\n", status); + + clear_context_free(clear); + + return 1; +} + +int test_ClearDecompressExample2() +{ + int status; + BYTE* pSrcData; + UINT32 SrcSize; + UINT32 DstSize; + BYTE* pDstData = NULL; + CLEAR_CONTEXT* clear; + + clear = clear_context_new(FALSE); + + SrcSize = sizeof(TEST_CLEAR_EXAMPLE_2) - 1; + pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_2; + + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + + printf("clear_decompress example 2 status: %d\n", status); + + clear_context_free(clear); + + return 1; +} + +int test_ClearDecompressExample3() +{ + int status; + BYTE* pSrcData; + UINT32 SrcSize; + UINT32 DstSize; + BYTE* pDstData = NULL; + CLEAR_CONTEXT* clear; + + clear = clear_context_new(FALSE); + + SrcSize = sizeof(TEST_CLEAR_EXAMPLE_3) - 1; + pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_3; + + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + + printf("clear_decompress example 3 status: %d\n", status); + + clear_context_free(clear); + + return 1; +} + +int test_ClearDecompressExample4() +{ + int status; + BYTE* pSrcData; + UINT32 SrcSize; + UINT32 DstSize; + BYTE* pDstData = NULL; + CLEAR_CONTEXT* clear; + + clear = clear_context_new(FALSE); + + SrcSize = sizeof(TEST_CLEAR_EXAMPLE_4) - 1; + pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_4; + + status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize); + + printf("clear_decompress example 4 status: %d\n", status); + + clear_context_free(clear); + + return 1; +} + +int TestFreeRDPCodecClear(int argc, char* argv[]) +{ + //test_ClearDecompressExample1(); + + //test_ClearDecompressExample2(); + + //test_ClearDecompressExample3(); + + test_ClearDecompressExample4(); + + return 0; +} + diff --git a/libfreerdp/codec/test/TestFreeRDPCodecZGfx.c b/libfreerdp/codec/test/TestFreeRDPCodecZGfx.c new file mode 100644 index 000000000..7284424e5 --- /dev/null +++ b/libfreerdp/codec/test/TestFreeRDPCodecZGfx.c @@ -0,0 +1,10 @@ +#include +#include + +#include + +int TestFreeRDPCodecZGfx(int argc, char* argv[]) +{ + return 0; +} + diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c new file mode 100644 index 000000000..5129296b7 --- /dev/null +++ b/libfreerdp/codec/zgfx.c @@ -0,0 +1,417 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * ZGFX (RDP8) Bulk Data Compression + * + * Copyright 2014 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 + +/** + * RDP8 Compressor Limits: + * + * Maximum number of uncompressed bytes in a single segment: 65535 + * Maximum match distance / minimum history size: 2500000 bytes. + * Maximum number of segments: 65535 + * Maximum expansion of a segment (when compressed size exceeds uncompressed): 1000 bytes + * Minimum match length: 3 bytes + */ + +struct _ZGFX_TOKEN +{ + int prefixLength; + int prefixCode; + int valueBits; + int tokenType; + UINT32 valueBase; +}; +typedef struct _ZGFX_TOKEN ZGFX_TOKEN; + +static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] = +{ + // len code vbits type vbase + { 1, 0, 8, 0, 0 }, // 0 + { 5, 17, 5, 1, 0 }, // 10001 + { 5, 18, 7, 1, 32 }, // 10010 + { 5, 19, 9, 1, 160 }, // 10011 + { 5, 20, 10, 1, 672 }, // 10100 + { 5, 21, 12, 1, 1696 }, // 10101 + { 5, 24, 0, 0, 0x00 }, // 11000 + { 5, 25, 0, 0, 0x01 }, // 11001 + { 6, 44, 14, 1, 5792 }, // 101100 + { 6, 45, 15, 1, 22176 }, // 101101 + { 6, 52, 0, 0, 0x02 }, // 110100 + { 6, 53, 0, 0, 0x03 }, // 110101 + { 6, 54, 0, 0, 0xFF }, // 110110 + { 7, 92, 18, 1, 54944 }, // 1011100 + { 7, 93, 20, 1, 317088 }, // 1011101 + { 7, 110, 0, 0, 0x04 }, // 1101110 + { 7, 111, 0, 0, 0x05 }, // 1101111 + { 7, 112, 0, 0, 0x06 }, // 1110000 + { 7, 113, 0, 0, 0x07 }, // 1110001 + { 7, 114, 0, 0, 0x08 }, // 1110010 + { 7, 115, 0, 0, 0x09 }, // 1110011 + { 7, 116, 0, 0, 0x0A }, // 1110100 + { 7, 117, 0, 0, 0x0B }, // 1110101 + { 7, 118, 0, 0, 0x3A }, // 1110110 + { 7, 119, 0, 0, 0x3B }, // 1110111 + { 7, 120, 0, 0, 0x3C }, // 1111000 + { 7, 121, 0, 0, 0x3D }, // 1111001 + { 7, 122, 0, 0, 0x3E }, // 1111010 + { 7, 123, 0, 0, 0x3F }, // 1111011 + { 7, 124, 0, 0, 0x40 }, // 1111100 + { 7, 125, 0, 0, 0x80 }, // 1111101 + { 8, 188, 20, 1, 1365664 }, // 10111100 + { 8, 189, 21, 1, 2414240 }, // 10111101 + { 8, 252, 0, 0, 0x0C }, // 11111100 + { 8, 253, 0, 0, 0x38 }, // 11111101 + { 8, 254, 0, 0, 0x39 }, // 11111110 + { 8, 255, 0, 0, 0x66 }, // 11111111 + { 9, 380, 22, 1, 4511392 }, // 101111100 + { 9, 381, 23, 1, 8705696 }, // 101111101 + { 9, 382, 24, 1, 17094304 }, // 101111110 + { 0 } +}; + +#define zgfx_GetBits(_zgfx, _nbits) \ + while (_zgfx->cBitsCurrent < _nbits) { \ + _zgfx->BitsCurrent <<= 8; \ + if (_zgfx->pbInputCurrent < _zgfx->pbInputEnd) \ + _zgfx->BitsCurrent += *(_zgfx->pbInputCurrent)++; \ + _zgfx->cBitsCurrent += 8; \ + } \ + _zgfx->cBitsRemaining -= _nbits; \ + _zgfx->cBitsCurrent -= _nbits; \ + _zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \ + _zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1); + +void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, BYTE* src, UINT32 count) +{ + UINT32 front; + UINT32 residue; + + if (count <= 0) + return; + + if (count > zgfx->HistoryBufferSize) + { + residue = count - zgfx->HistoryBufferSize; + count = zgfx->HistoryBufferSize; + src += residue; + + zgfx->HistoryIndex = (zgfx->HistoryIndex + residue) % zgfx->HistoryBufferSize; + } + + if (zgfx->HistoryIndex + count <= zgfx->HistoryBufferSize) + { + CopyMemory(&(zgfx->HistoryBuffer[zgfx->HistoryIndex]), src, count); + + if ((zgfx->HistoryIndex += count) == zgfx->HistoryBufferSize) + zgfx->HistoryIndex = 0; + } + else + { + front = zgfx->HistoryBufferSize - zgfx->HistoryIndex; + CopyMemory(&(zgfx->HistoryBuffer[zgfx->HistoryIndex]), src, front); + CopyMemory(zgfx->HistoryBuffer, &src[front], count - front); + zgfx->HistoryIndex = count - front; + } +} + +void zgfx_history_buffer_ring_read(ZGFX_CONTEXT* zgfx, int offset, BYTE* dst, UINT32 count) +{ + UINT32 front; + UINT32 index; + UINT32 bytes; + UINT32 valid; + UINT32 bytesLeft; + BYTE* dptr = dst; + BYTE* origDst = dst; + + if (count <= 0) + return; + + bytesLeft = count; + + index = (zgfx->HistoryIndex + zgfx->HistoryBufferSize - offset) % zgfx->HistoryBufferSize; + + bytes = MIN(bytesLeft, offset); + + if ((index + bytes) <= zgfx->HistoryBufferSize) + { + CopyMemory(dptr, &(zgfx->HistoryBuffer[index]), bytes); + } + else + { + front = zgfx->HistoryBufferSize - index; + CopyMemory(dptr, &(zgfx->HistoryBuffer[index]), front); + CopyMemory(&dptr[front], zgfx->HistoryBuffer, bytes - front); + } + + if ((bytesLeft -= bytes) == 0) + return; + + dptr += bytes; + valid = bytes; + + do + { + bytes = valid; + + if (bytes > bytesLeft) + bytes = bytesLeft; + + CopyMemory(dptr, origDst, bytes); + dptr += bytes; + valid <<= 1; + } + while ((bytesLeft -= bytes) > 0); +} + +int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegment) +{ + BYTE c; + BYTE flags; + int extra; + int opIndex; + int haveBits; + int inPrefix; + UINT32 count; + UINT32 distance; + + if (cbSegment < 1) + return -1; + + flags = pbSegment[0]; /* header (1 byte) */ + + pbSegment++; + cbSegment--; + + zgfx->OutputCount = 0; + + if (!(flags & PACKET_COMPRESSED)) + { + zgfx_history_buffer_ring_write(zgfx, pbSegment, cbSegment); + CopyMemory(zgfx->OutputBuffer, pbSegment, cbSegment); + zgfx->OutputCount = cbSegment; + + return 1; + } + + zgfx->pbInputCurrent = pbSegment; + zgfx->pbInputEnd = &pbSegment[cbSegment - 1]; + + /* NumberOfBitsToDecode = ((NumberOfBytesToDecode - 1) * 8) - ValueOfLastByte */ + zgfx->cBitsRemaining = 8 * (cbSegment - 1) - *zgfx->pbInputEnd; + zgfx->cBitsCurrent = 0; + zgfx->BitsCurrent = 0; + + while (zgfx->cBitsRemaining) + { + haveBits = 0; + inPrefix = 0; + + for (opIndex = 0; ZGFX_TOKEN_TABLE[opIndex].prefixLength != 0; opIndex++) + { + while (haveBits < ZGFX_TOKEN_TABLE[opIndex].prefixLength) + { + zgfx_GetBits(zgfx, 1); + inPrefix = (inPrefix << 1) + zgfx->bits; + haveBits++; + } + + if (inPrefix == ZGFX_TOKEN_TABLE[opIndex].prefixCode) + { + if (ZGFX_TOKEN_TABLE[opIndex].tokenType == 0) + { + /* Literal */ + + zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); + c = (BYTE) (ZGFX_TOKEN_TABLE[opIndex].valueBase + zgfx->bits); + + zgfx->HistoryBuffer[zgfx->HistoryIndex] = c; + + if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize) + zgfx->HistoryIndex = 0; + + zgfx->OutputBuffer[zgfx->OutputCount++] = c; + } + else + { + zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits); + distance = ZGFX_TOKEN_TABLE[opIndex].valueBase + zgfx->bits; + + if (distance != 0) + { + /* Match */ + + zgfx_GetBits(zgfx, 1); + + if (zgfx->bits == 0) + { + count = 3; + } + else + { + count = 4; + extra = 2; + + zgfx_GetBits(zgfx, 1); + + while (zgfx->bits == 1) + { + count *= 2; + extra++; + + zgfx_GetBits(zgfx, 1); + } + + zgfx_GetBits(zgfx, extra); + count += zgfx->bits; + } + + zgfx_history_buffer_ring_read(zgfx, distance, &(zgfx->OutputBuffer[zgfx->OutputCount]), count); + zgfx_history_buffer_ring_write(zgfx, &(zgfx->OutputBuffer[zgfx->OutputCount]), count); + zgfx->OutputCount += count; + } + else + { + /* Unencoded */ + + zgfx_GetBits(zgfx, 15); + count = zgfx->bits; + + zgfx->cBitsRemaining -= zgfx->cBitsCurrent; + zgfx->cBitsCurrent = 0; + zgfx->BitsCurrent = 0; + + CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent, count); + zgfx_history_buffer_ring_write(zgfx, zgfx->pbInputCurrent, count); + + zgfx->pbInputCurrent += count; + zgfx->cBitsRemaining -= (8 * count); + zgfx->OutputCount += count; + } + } + + break; + } + } + } + + return 1; +} + +int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) +{ + int status; + BYTE descriptor; + + if (SrcSize < 1) + return -1; + + descriptor = pSrcData[0]; /* descriptor (1 byte) */ + + if (descriptor == ZGFX_SEGMENTED_SINGLE) + { + status = zgfx_decompress_segment(zgfx, &pSrcData[1], SrcSize - 1); + + *ppDstData = (BYTE*) malloc(zgfx->OutputCount); + *pDstSize = zgfx->OutputCount; + + CopyMemory(*ppDstData, zgfx->OutputBuffer, zgfx->OutputCount); + } + else if (descriptor == ZGFX_SEGMENTED_MULTIPART) + { + UINT32 segmentSize; + UINT16 segmentNumber; + UINT16 segmentCount; + UINT32 segmentOffset; + UINT32 uncompressedSize; + BYTE* pConcatenated; + + segmentOffset = 7; + segmentCount = *((UINT16*) &pSrcData[1]); /* segmentCount (2 bytes) */ + uncompressedSize = *((UINT32*) &pSrcData[3]); /* uncompressedSize (4 bytes) */ + + pConcatenated = (BYTE*) malloc(uncompressedSize); + + *ppDstData = pConcatenated; + *pDstSize = uncompressedSize; + + for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++) + { + segmentSize = *((UINT32*) &pSrcData[segmentOffset]); /* segmentSize (4 bytes) */ + segmentOffset += 4; + + status = zgfx_decompress_segment(zgfx, &pSrcData[segmentOffset], segmentSize); + segmentOffset += segmentSize; + + CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount); + pConcatenated += zgfx->OutputCount; + } + } + else + { + return -1; + } + + return 1; +} + +int zgfx_compress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags) +{ + return 1; +} + +void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush) +{ + zgfx->HistoryIndex = 0; +} + +ZGFX_CONTEXT* zgfx_context_new(BOOL Compressor) +{ + ZGFX_CONTEXT* zgfx; + + zgfx = (ZGFX_CONTEXT*) calloc(1, sizeof(ZGFX_CONTEXT)); + + if (zgfx) + { + zgfx->Compressor = Compressor; + + zgfx->HistoryBufferSize = sizeof(zgfx->HistoryBuffer); + + zgfx_context_reset(zgfx, FALSE); + } + + return zgfx; +} + +void zgfx_context_free(ZGFX_CONTEXT* zgfx) +{ + if (zgfx) + { + free(zgfx); + } +} + diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index 8f1455b81..e04230f37 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -517,11 +517,16 @@ out_free: void freerdp_dynamic_channel_collection_free(rdpSettings* settings) { - UINT32 index; + int j; + UINT32 i; - for (index = 0; index < settings->DynamicChannelCount; index++) + for (i = 0; i < settings->DynamicChannelCount; i++) { - free(settings->DynamicChannelArray[index]); + for (j = 0; j < settings->DynamicChannelArray[i]->argc; j++) + free(settings->DynamicChannelArray[i]->argv[j]); + + free(settings->DynamicChannelArray[i]->argv); + free(settings->DynamicChannelArray[i]); } free(settings->DynamicChannelArray); diff --git a/libfreerdp/core/client.c b/libfreerdp/core/client.c index cc13e28f8..5f4aec1e6 100644 --- a/libfreerdp/core/client.c +++ b/libfreerdp/core/client.c @@ -72,27 +72,14 @@ rdpMcsChannel* freerdp_channels_find_channel_by_name(rdpRdp* rdp, const char* na return NULL; } -/** - * this is called shortly after the application starts and - * before any other function in the file - * called only from main thread - */ -int freerdp_channels_global_init(void) -{ - return 0; -} - -int freerdp_channels_global_uninit(void) -{ - return 0; -} - rdpChannels* freerdp_channels_new(void) { rdpChannels* channels; - channels = (rdpChannels*) malloc(sizeof(rdpChannels)); - ZeroMemory(channels, sizeof(rdpChannels)); + channels = (rdpChannels*) calloc(1, sizeof(rdpChannels)); + + if (!channels) + return NULL; channels->MsgPipe = MessagePipe_New(); @@ -280,10 +267,6 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* eve switch (GetMessageClass(event->id)) { - case DebugChannel_Class: - name = "rdpdbg"; - break; - case CliprdrChannel_Class: name = "cliprdr"; break; diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index 9a780eca5..f40bd6a28 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -169,8 +169,6 @@ BOOL freerdp_connect(freerdp* instance) update_recv_surfcmds(update, Stream_Length(s) , s); update->EndPaint(update->context); Stream_Release(s); - - StreamPool_Return(rdp->transport->ReceivePool, s); } pcap_close(update->pcap_rfx); diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index 052e8957d..7a529d256 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -102,10 +102,11 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3 if (dataFlags & CHANNEL_FLAG_FIRST) { - if (plugin->data_in != NULL) - Stream_Free(plugin->data_in, TRUE); + if (plugin->data_in) + Stream_Release(plugin->data_in); - plugin->data_in = Stream_New(NULL, totalLength); + plugin->data_in = StreamPool_Take(plugin->pool, totalLength); + Stream_AddRef(plugin->data_in); } s = plugin->data_in; @@ -178,6 +179,7 @@ static void* svc_plugin_thread_func(void* arg) IFCALL(plugin->connect_callback, plugin); SetEvent(plugin->started); + while (1) { if (!MessageQueue_Wait(plugin->MsgPipe->In)) @@ -192,6 +194,7 @@ static void* svc_plugin_thread_func(void* arg) { data = (wStream*) message.wParam; IFCALL(plugin->receive_callback, plugin, data); + Stream_Release(data); } else if (message.id == 1) { @@ -236,7 +239,12 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin) MessagePipe_Free(plugin->MsgPipe); CloseHandle(plugin->thread); - CloseHandle(plugin->started); + + if (plugin->started) + { + CloseHandle(plugin->started); + plugin->started = NULL; + } plugin->channel_entry_points.pVirtualChannelClose(plugin->OpenHandle); @@ -246,10 +254,10 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin) plugin->data_in = NULL; } - IFCALL(plugin->terminate_callback, plugin); - svc_plugin_remove_open_handle_data(plugin->OpenHandle); svc_plugin_remove_init_handle_data(plugin->InitHandle); + + IFCALL(plugin->terminate_callback, plugin); } static VOID VCAPITYPE svc_plugin_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) @@ -295,11 +303,27 @@ void svc_plugin_init(rdpSvcPlugin* plugin, CHANNEL_ENTRY_POINTS* pEntryPoints) plugin->channel_entry_points.pInterface = *(plugin->channel_entry_points.ppInterface); plugin->channel_entry_points.ppInterface = &(plugin->channel_entry_points.pInterface); - plugin->started = CreateEvent(NULL,TRUE,FALSE,NULL); + plugin->started = CreateEvent(NULL, TRUE, FALSE, NULL); + plugin->pool = StreamPool_New(TRUE, 10); svc_plugin_add_init_handle_data(plugin->InitHandle, plugin); } +void svc_plugin_terminate(rdpSvcPlugin* plugin) +{ + if (plugin->pool) + { + StreamPool_Free(plugin->pool); + plugin->pool = NULL; + } + + if (plugin->started) + { + CloseHandle(plugin->started); + plugin->started = NULL; + } +} + int svc_plugin_send(rdpSvcPlugin* plugin, wStream* data_out) { UINT32 status = 0; diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index b1b945b9a..f56a556d8 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -326,6 +326,8 @@ WINPR_API void CountdownEvent_Free(wCountdownEvent* countdown); /* Hash Table */ +typedef void (*KEY_VALUE_FREE_FN)(void* context, void* key, void* value); + struct _wHashTable { BOOL synchronized; @@ -342,6 +344,9 @@ struct _wHashTable unsigned long (*hashFunction)(void* key); void (*keyDeallocator)(void* key); void (*valueDeallocator)(void* value); + + void* context; + KEY_VALUE_FREE_FN pfnKeyValueFree; }; typedef struct _wHashTable wHashTable; @@ -354,6 +359,8 @@ WINPR_API BOOL HashTable_ContainsKey(wHashTable* table, void* key); WINPR_API BOOL HashTable_ContainsValue(wHashTable* table, void* value); WINPR_API void* HashTable_GetItemValue(wHashTable* table, void* key); WINPR_API BOOL HashTable_SetItemValue(wHashTable* table, void* key, void* value); +WINPR_API void HashTable_SetFreeFunction(wHashTable* table, void* context, KEY_VALUE_FREE_FN pfnKeyValueFree); +WINPR_API int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys); WINPR_API wHashTable* HashTable_New(BOOL synchronized); WINPR_API void HashTable_Free(wHashTable* table); diff --git a/winpr/libwinpr/utils/collections/HashTable.c b/winpr/libwinpr/utils/collections/HashTable.c index 15ae5175e..fcbe4aa3d 100644 --- a/winpr/libwinpr/utils/collections/HashTable.c +++ b/winpr/libwinpr/utils/collections/HashTable.c @@ -368,6 +368,9 @@ void HashTable_Clear(wHashTable* table) { nextPair = pair->next; + if (table->pfnKeyValueFree) + table->pfnKeyValueFree(table->context, pair->key, pair->value); + if (table->keyDeallocator) table->keyDeallocator((void*) pair->key); @@ -389,6 +392,48 @@ void HashTable_Clear(wHashTable* table) LeaveCriticalSection(&table->lock); } +/** + * Gets the list of keys as an array + */ + +int HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys) +{ + int iKey; + int count; + int index; + ULONG_PTR* pKeys; + wKeyValuePair* pair; + wKeyValuePair* nextPair; + + if (table->synchronized) + EnterCriticalSection(&table->lock); + + iKey = 0; + count = table->numOfElements; + pKeys = (ULONG_PTR*) calloc(count, sizeof(ULONG_PTR)); + + for (index = 0; index < table->numOfBuckets; index++) + { + pair = table->bucketArray[index]; + + while (pair) + { + nextPair = pair->next; + + pKeys[iKey++] = (ULONG_PTR) pair->key; + + pair = nextPair; + } + } + + if (table->synchronized) + LeaveCriticalSection(&table->lock); + + *ppKeys = pKeys; + + return count; +} + /** * Determines whether the HashTable contains a specific key. */ @@ -465,6 +510,12 @@ BOOL HashTable_ContainsValue(wHashTable* table, void* value) return status; } +void HashTable_SetFreeFunction(wHashTable* table, void* context, KEY_VALUE_FREE_FN pfnKeyValueFree) +{ + table->context = context; + table->pfnKeyValueFree = pfnKeyValueFree; +} + /** * Construction, Destruction */ @@ -479,7 +530,7 @@ wHashTable* HashTable_New(BOOL synchronized) if (table) { table->synchronized = synchronized; - InitializeCriticalSectionAndSpinCount(&table->lock, 4000); + InitializeCriticalSectionAndSpinCount(&(table->lock), 4000); table->numOfBuckets = 64; table->numOfElements = 0; @@ -537,6 +588,8 @@ void HashTable_Free(wHashTable* table) } } + DeleteCriticalSection(&(table->lock)); + free(table->bucketArray); free(table); } diff --git a/winpr/libwinpr/utils/collections/ListDictionary.c b/winpr/libwinpr/utils/collections/ListDictionary.c index ca65d8a08..918bee44c 100644 --- a/winpr/libwinpr/utils/collections/ListDictionary.c +++ b/winpr/libwinpr/utils/collections/ListDictionary.c @@ -144,8 +144,7 @@ int ListDictionary_GetKeys(wListDictionary* listDictionary, ULONG_PTR** ppKeys) } } - pKeys = (ULONG_PTR*) malloc(sizeof(ULONG_PTR) * count); - ZeroMemory(pKeys, sizeof(ULONG_PTR) * count); + pKeys = (ULONG_PTR*) calloc(count, sizeof(ULONG_PTR)); index = 0; diff --git a/winpr/libwinpr/utils/collections/StreamPool.c b/winpr/libwinpr/utils/collections/StreamPool.c index 5dd0d852b..c95875fbe 100644 --- a/winpr/libwinpr/utils/collections/StreamPool.c +++ b/winpr/libwinpr/utils/collections/StreamPool.c @@ -182,6 +182,11 @@ void StreamPool_Return(wStreamPool* pool, wStream* s) pool->aCapacity *= 2; pool->aArray = (wStream**) realloc(pool->aArray, sizeof(wStream*) * pool->aCapacity); } + else if ((pool->aSize + 1) * 3 < pool->aCapacity) + { + pool->aCapacity /= 2; + pool->aArray = (wStream**) realloc(pool->aArray, sizeof(wStream*) * pool->aCapacity); + } pool->aArray[(pool->aSize)++] = s; StreamPool_RemoveUsed(pool, s);