Merge pull request #1923 from awakecoding/egfx

MS-RDPEGFX Initial Implementation (WIP)
This commit is contained in:
Marc-André Moreau 2014-06-23 12:26:40 -04:00
commit d0a0f61236
90 changed files with 4306 additions and 1591 deletions

View File

@ -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;
}

View File

@ -31,7 +31,6 @@
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/cliprdr.h>
#include "cliprdr_main.h"

View File

@ -31,7 +31,6 @@
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/cliprdr.h>
#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);
}

View File

@ -24,6 +24,7 @@
#include <winpr/stream.h>
#include <freerdp/utils/debug.h>
#include <freerdp/utils/svc_plugin.h>
struct cliprdr_plugin
{

View File

@ -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;

View File

@ -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 */

View File

@ -29,45 +29,44 @@
#include <winpr/stream.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#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;
}

View File

@ -26,6 +26,17 @@
#include <freerdp/client/drdynvc.h>
#include <freerdp/utils/svc_plugin.h>
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;

View File

@ -3,8 +3,6 @@
* Dynamic Virtual Channel Manager
*
* Copyright 2010-2011 Vic Lee
* Copyright 2014 Thincast Technologies GmbH
* Copyright 2014 Armin Novak <armin.novak@thincast.com>
*
* 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 <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -33,61 +28,45 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <freerdp/addin.h>
#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();
}

View File

@ -23,6 +23,7 @@
#include <freerdp/dvc.h>
#include <freerdp/addin.h>
#include <winpr/synch.h>
#include <winpr/collections.h>
#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);

View File

@ -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;

View File

@ -47,13 +47,12 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <winpr/interlocked.h>
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <winpr/stream.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/channels/rdpdr.h>
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);

View File

@ -31,7 +31,6 @@
#include <winpr/crt.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/channels/rdpdr.h>
#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;

View File

@ -28,11 +28,10 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/interlocked.h>
#include <winpr/stream.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/utils/svc_plugin.h>
#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;

View File

@ -30,8 +30,6 @@
#include <string.h>
#include <winspool.h>
#include <freerdp/utils/svc_plugin.h>
#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;

View File

@ -31,7 +31,6 @@
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/utils/rail.h>
#include <freerdp/rail.h>
@ -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 |

View File

@ -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;
}

View File

@ -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}

View File

@ -0,0 +1,111 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Graphics Pipeline Extension
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/stream.h>
#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;
}

View File

@ -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 <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -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 <winpr/crt.h>
#include <winpr/stream.h>
#endif /* __SAMPLE_MAIN_H */
#include <freerdp/channels/rdpgfx.h>
#include "rdpgfx_main.h"
int rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd);
#endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_CODEC_H */

View File

@ -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;
}

View File

@ -25,14 +25,20 @@
#include <freerdp/channels/rdpgfx.h>
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 */

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
* FreeRDP: A Remote Desktop Protocol Implementation
* Graphics Pipeline Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2013-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -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 <freerdp/dvc.h>
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <winpr/wlog.h>
#include <winpr/collections.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/codec/zgfx.h>
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 */

View File

@ -20,12 +20,11 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/wtypes.h>
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/utils/svc_plugin.h>
#import <AudioToolbox/AudioToolbox.h>
@ -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;
}
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;
}

View File

@ -29,7 +29,6 @@
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/utils/svc_plugin.h>
#include <AudioToolbox/AudioToolbox.h>
#include <AudioToolbox/AudioQueue.h>
@ -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;
}

View File

@ -37,7 +37,6 @@
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/utils/svc_plugin.h>
#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;
}

View File

@ -34,7 +34,6 @@
#include <freerdp/types.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/utils/svc_plugin.h>
#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;

View File

@ -1,23 +0,0 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
define_channel("sample")
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -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})

View File

@ -1,35 +0,0 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
define_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")

View File

@ -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

View File

@ -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 <sys/time.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#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;
}

View File

@ -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 <string>
#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;
}

View File

@ -53,7 +53,6 @@
#include <freerdp/freerdp.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/utils/svc_plugin.h>
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;

View File

@ -30,7 +30,6 @@
#include <winpr/print.h>
#include <winpr/stream.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/channels/rdpdr.h>
#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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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)

View File

@ -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;
}

View File

@ -31,7 +31,6 @@
#include <freerdp/freerdp.h>
#include <freerdp/constants.h>
#include <freerdp/utils/event.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/file.h>
#include <freerdp/client/cmdline.h>

View File

@ -43,9 +43,7 @@
#include <freerdp/freerdp.h>
#include <freerdp/constants.h>
#include <freerdp/utils/event.h>
#include <freerdp/utils/svc_plugin.h>
//#include <freerdp/client/file.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/client/channels.h>
#include <freerdp/channels/channels.h>
@ -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);
}

View File

@ -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

View File

@ -154,9 +154,9 @@ int main(int argc, char *argv[])
fprintf(fp, "\t\t\t\t\t<para>%s</para>\n", format);
fprintf(fp, "\t\t\t\t</listitem>\n");
fprintf(fp, "\t\t\t</varlistentry>\n");
free(name);
free(format);
free(text);
free((void*) name);
free((void*) format);
free((void*) text);
}
fprintf(fp, "\t\t</variablelist>\n");
fprintf(fp, "\t</refsect1>\n");

View File

@ -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);
}
}

View File

@ -23,6 +23,7 @@
#include <freerdp/freerdp.h>
#include <freerdp/client/channels.h>
#include <freerdp/client/rdpei.h>
#include <freerdp/client/rdpgfx.h>
int xf_on_channel_connected(freerdp* instance, const char* name, void* pInterface);
int xf_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface);

View File

@ -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)

View File

@ -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

View File

@ -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);

672
client/X11/xf_gfx.c Normal file
View File

@ -0,0 +1,672 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* X11 Graphics Pipeline
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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;
}

54
client/X11/xf_gfx.h Normal file
View File

@ -0,0 +1,54 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* X11 Graphics Pipeline
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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 */

View File

@ -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;

View File

@ -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)

View File

@ -28,6 +28,14 @@ typedef struct xf_context xfContext;
#include "xf_monitor.h"
#include "xf_channels.h"
#include <freerdp/gdi/gdi.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/codec/nsc.h>
#include <freerdp/codec/clear.h>
#include <freerdp/codec/color.h>
#include <freerdp/codec/bitmap.h>
#include <freerdp/codec/region.h>
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);

View File

@ -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")
{

View File

@ -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;

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -0,0 +1,57 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* ClearCodec Bitmap Compression
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CODEC_CLEAR_H
#define FREERDP_CODEC_CLEAR_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#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 */

View File

@ -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
}

View File

@ -0,0 +1,69 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* ZGFX (RDP8) Bulk Data Compression
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CODEC_ZGFX_H
#define FREERDP_CODEC_ZGFX_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/codec/bulk.h>
#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 */

View File

@ -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 */

View File

@ -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);

View File

@ -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

View File

@ -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)

340
libfreerdp/codec/clear.c Normal file
View File

@ -0,0 +1,340 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* ClearCodec Bitmap Compression
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/bitstream.h>
#include <freerdp/codec/clear.h>
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);
}
}

View File

@ -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;
}

View File

@ -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])

View File

@ -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);

View File

@ -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(&region->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;
}

View File

@ -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

View File

@ -0,0 +1,144 @@
#include <winpr/crt.h>
#include <winpr/print.h>
#include <freerdp/codec/clear.h>
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;
}

View File

@ -0,0 +1,10 @@
#include <winpr/crt.h>
#include <winpr/print.h>
#include <freerdp/codec/zgfx.h>
int TestFreeRDPCodecZGfx(int argc, char* argv[])
{
return 0;
}

417
libfreerdp/codec/zgfx.c Normal file
View File

@ -0,0 +1,417 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* ZGFX (RDP8) Bulk Data Compression
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/bitstream.h>
#include <freerdp/codec/zgfx.h>
/**
* 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);
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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);