channel rdpei hardend

This commit is contained in:
Martin Haimberger 2015-06-09 03:46:10 -07:00
parent d7636d0e28
commit 6348e41479
6 changed files with 412 additions and 221 deletions

View File

@ -3,6 +3,8 @@
* Input Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -106,7 +108,7 @@ struct _RDPEI_PLUGIN
};
typedef struct _RDPEI_PLUGIN RDPEI_PLUGIN;
int rdpei_send_frame(RdpeiClientContext* context);
WIN32ERROR rdpei_send_frame(RdpeiClientContext* context);
const char* RDPEI_EVENTID_STRINGS[] =
{
@ -119,7 +121,7 @@ const char* RDPEI_EVENTID_STRINGS[] =
"EVENTID_DISMISS_HOVERING_CONTACT"
};
int rdpei_add_frame(RdpeiClientContext* context)
WIN32ERROR rdpei_add_frame(RdpeiClientContext* context)
{
int i;
RDPINPUT_CONTACT_DATA* contact;
@ -151,7 +153,7 @@ int rdpei_add_frame(RdpeiClientContext* context)
}
}
return 1;
return CHANNEL_RC_OK;
}
static void* rdpei_schedule_thread(void* arg)
@ -160,12 +162,20 @@ static void* rdpei_schedule_thread(void* arg)
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) arg;
RdpeiClientContext* context = (RdpeiClientContext*) rdpei->iface.pInterface;
HANDLE hdl[] = {rdpei->event, rdpei->stopEvent};
WIN32ERROR error;
if (!rdpei)
{
ExitThread((DWORD)ERROR_INVALID_PARAMETER);
return NULL;
}
if (!context)
{
ExitThread((DWORD)ERROR_INVALID_PARAMETER);
return NULL;
}
while (1)
{
@ -175,10 +185,23 @@ static void* rdpei_schedule_thread(void* arg)
EnterCriticalSection(&rdpei->lock);
rdpei_add_frame(context);
if ((error = rdpei_add_frame(context)))
{
WLog_ERR(TAG, "rdpei_add_frame failed with error %lu!", error);
ExitThread((DWORD)error);
return NULL;
}
if (rdpei->frame.contactCount > 0)
rdpei_send_frame(context);
{
if ((error = rdpei_send_frame(context)))
{
WLog_ERR(TAG, "rdpei_send_frame failed with error %lu!", error);
ExitThread((DWORD)error);
return NULL;
}
}
if (status == WAIT_OBJECT_0)
ResetEvent(rdpei->event);
@ -191,9 +214,9 @@ static void* rdpei_schedule_thread(void* arg)
return NULL;
}
int rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s, UINT16 eventId, UINT32 pduLength)
WIN32ERROR rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s, UINT16 eventId, UINT32 pduLength)
{
int status;
WIN32ERROR status;
Stream_SetPosition(s, 0);
Stream_Write_UINT16(s, eventId); /* eventId (2 bytes) */
@ -210,9 +233,9 @@ int rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s, UINT16 eventId,
return status;
}
int rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback)
WIN32ERROR rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback)
{
int status;
WIN32ERROR status;
wStream* s;
UINT32 flags;
UINT32 pduLength;
@ -224,6 +247,11 @@ int rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback)
pduLength = RDPINPUT_HEADER_LENGTH + 10;
s = Stream_New(NULL, pduLength);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
Stream_Write_UINT32(s, flags); /* flags (4 bytes) */
@ -259,7 +287,7 @@ void rdpei_print_contact_flags(UINT32 contactFlags)
WLog_DBG(TAG, " CONTACT_FLAG_CANCELED");
}
int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
WIN32ERROR rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
{
UINT32 index;
int rectSize = 2;
@ -278,7 +306,11 @@ int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
*/
rdpei_write_8byte_unsigned(s, frame->frameOffset * 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */
Stream_EnsureRemainingCapacity(s, (size_t) frame->contactCount * 64);
if (!Stream_EnsureRemainingCapacity(s, (size_t) frame->contactCount * 64))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
return CHANNEL_RC_NO_MEMORY;
}
for (index = 0; index < frame->contactCount; index++)
{
@ -335,18 +367,23 @@ int rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
}
}
return 0;
return CHANNEL_RC_OK;
}
int rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH_FRAME* frame)
WIN32ERROR rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH_FRAME* frame)
{
int status;
WIN32ERROR status;
wStream* s;
UINT32 pduLength;
pduLength = 64 + (frame->contactCount * 64);
s = Stream_New(NULL, pduLength);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Seek(s, RDPINPUT_HEADER_LENGTH);
/**
@ -357,7 +394,12 @@ int rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH_
rdpei_write_2byte_unsigned(s, 1); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */
rdpei_write_touch_frame(s, frame);
if ((status = rdpei_write_touch_frame(s, frame)))
{
WLog_ERR(TAG, "rdpei_write_touch_frame failed with error %lu!", status);
Stream_Free(s, TRUE);
return status;
}
Stream_SealLength(s);
pduLength = Stream_Length(s);
@ -368,7 +410,7 @@ int rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, RDPINPUT_TOUCH_
return status;
}
int rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
WIN32ERROR rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
{
UINT32 protocolVersion;
@ -382,33 +424,38 @@ int rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
}
#endif
return 0;
return CHANNEL_RC_OK;
}
int rdpei_recv_suspend_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
WIN32ERROR rdpei_recv_suspend_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
{
RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface;
WIN32ERROR error = CHANNEL_RC_OK;
if (rdpei->SuspendTouch)
rdpei->SuspendTouch(rdpei);
IFCALLRET(rdpei->SuspendTouch, error, rdpei);
if (error)
WLog_ERR(TAG, "rdpei->SuspendTouch failed with error %lu!", error);
return 0;
return error;
}
int rdpei_recv_resume_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
WIN32ERROR rdpei_recv_resume_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
{
RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface;
WIN32ERROR error = CHANNEL_RC_OK;
if (rdpei->ResumeTouch)
rdpei->ResumeTouch(rdpei);
IFCALLRET(rdpei->ResumeTouch, error, rdpei);
if (error)
WLog_ERR(TAG, "rdpei->ResumeTouch failed with error %lu!", error);
return 0;
return error;
}
int rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
WIN32ERROR rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
{
UINT16 eventId;
UINT32 pduLength;
WIN32ERROR error;
Stream_Read_UINT16(s, eventId); /* eventId (2 bytes) */
Stream_Read_UINT32(s, pduLength); /* pduLength (4 bytes) */
@ -421,57 +468,70 @@ int rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s)
switch (eventId)
{
case EVENTID_SC_READY:
rdpei_recv_sc_ready_pdu(callback, s);
rdpei_send_cs_ready_pdu(callback);
if ((error = rdpei_recv_sc_ready_pdu(callback, s)))
{
WLog_ERR(TAG, "rdpei_recv_sc_ready_pdu failed with error %lu!", error);
return error;
}
if ((error = rdpei_send_cs_ready_pdu(callback)))
{
WLog_ERR(TAG, "rdpei_send_cs_ready_pdu failed with error %lu!", error);
return error;
}
break;
case EVENTID_SUSPEND_TOUCH:
rdpei_recv_suspend_touch_pdu(callback, s);
if ((error = rdpei_recv_suspend_touch_pdu(callback, s)))
{
WLog_ERR(TAG, "rdpei_recv_suspend_touch_pdu failed with error %lu!", error);
return error;
}
break;
case EVENTID_RESUME_TOUCH:
rdpei_recv_resume_touch_pdu(callback, s);
if ((error = rdpei_recv_resume_touch_pdu(callback, s)))
{
WLog_ERR(TAG, "rdpei_recv_resume_touch_pdu failed with error %lu!", error);
return error;
}
break;
default:
break;
}
return 0;
return CHANNEL_RC_OK;
}
static int rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
{
int status = 0;
RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback;
status = rdpei_recv_pdu(callback, data);
return status;
}
static int rdpei_on_close(IWTSVirtualChannelCallback* pChannelCallback)
static WIN32ERROR rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
{
RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback;
DEBUG_DVC("");
return rdpei_recv_pdu(callback, data);
}
static WIN32ERROR rdpei_on_close(IWTSVirtualChannelCallback* pChannelCallback)
{
RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback;
free(callback);
return 0;
return CHANNEL_RC_OK;
}
static int rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
static WIN32ERROR rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
IWTSVirtualChannel* pChannel, BYTE* Data, int* pbAccept,
IWTSVirtualChannelCallback** ppCallback)
{
RDPEI_CHANNEL_CALLBACK* callback;
RDPEI_LISTENER_CALLBACK* listener_callback = (RDPEI_LISTENER_CALLBACK*) pListenerCallback;
DEBUG_DVC("");
callback = (RDPEI_CHANNEL_CALLBACK*) malloc(sizeof(RDPEI_CHANNEL_CALLBACK));
ZeroMemory(callback, sizeof(RDPEI_CHANNEL_CALLBACK));
callback = (RDPEI_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPEI_CHANNEL_CALLBACK));
if (!callback)
{
WLog_ERR(TAG,"calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
callback->iface.OnDataReceived = rdpei_on_data_received;
callback->iface.OnClose = rdpei_on_close;
@ -482,45 +542,71 @@ static int rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallba
*ppCallback = (IWTSVirtualChannelCallback*) callback;
return 0;
return CHANNEL_RC_OK;
}
static int rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
static WIN32ERROR rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{
int status;
WIN32ERROR error;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) pPlugin;
DEBUG_DVC("");
rdpei->listener_callback = (RDPEI_LISTENER_CALLBACK*) malloc(sizeof(RDPEI_LISTENER_CALLBACK));
ZeroMemory(rdpei->listener_callback, sizeof(RDPEI_LISTENER_CALLBACK));
rdpei->listener_callback = (RDPEI_LISTENER_CALLBACK*) calloc(1 ,sizeof(RDPEI_LISTENER_CALLBACK));
if (!rdpei->listener_callback)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
rdpei->listener_callback->iface.OnNewChannelConnection = rdpei_on_new_channel_connection;
rdpei->listener_callback->plugin = pPlugin;
rdpei->listener_callback->channel_mgr = pChannelMgr;
status = pChannelMgr->CreateListener(pChannelMgr, RDPEI_DVC_CHANNEL_NAME, 0,
(IWTSListenerCallback*) rdpei->listener_callback, &(rdpei->listener));
if ((error = pChannelMgr->CreateListener(pChannelMgr, RDPEI_DVC_CHANNEL_NAME, 0,
(IWTSListenerCallback*) rdpei->listener_callback, &(rdpei->listener))))
{
WLog_ERR(TAG, "ChannelMgr->CreateListener failed with error %lu!", error);
goto error_out;
}
rdpei->listener->pInterface = rdpei->iface.pInterface;
InitializeCriticalSection(&rdpei->lock);
rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpei->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
rdpei_schedule_thread, (void*) rdpei, 0, NULL);
if (!(rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
goto error_out;
return status;
}
if (!(rdpei->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
goto error_out;
}
if (!(rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
rdpei_schedule_thread, (void*) rdpei, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
goto error_out;
}
return error;
error_out:
CloseHandle(rdpei->stopEvent);
CloseHandle(rdpei->event);
free(rdpei->listener_callback);
return error;
}
static int rdpei_plugin_terminated(IWTSPlugin* pPlugin)
static WIN32ERROR rdpei_plugin_terminated(IWTSPlugin* pPlugin)
{
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) pPlugin;
DEBUG_DVC("");
if (!pPlugin)
return -1;
return ERROR_INVALID_PARAMETER;
SetEvent(rdpei->stopEvent);
EnterCriticalSection(&rdpei->lock);
@ -537,7 +623,7 @@ static int rdpei_plugin_terminated(IWTSPlugin* pPlugin)
free(rdpei->context);
free(rdpei);
return 0;
return CHANNEL_RC_OK;
}
/**
@ -550,11 +636,12 @@ int rdpei_get_version(RdpeiClientContext* context)
return rdpei->version;
}
int rdpei_send_frame(RdpeiClientContext* context)
WIN32ERROR rdpei_send_frame(RdpeiClientContext* context)
{
UINT64 currentTime;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
RDPEI_CHANNEL_CALLBACK* callback = rdpei->listener_callback->channel_callback;
WIN32ERROR error;
currentTime = GetTickCount64();
@ -569,14 +656,18 @@ int rdpei_send_frame(RdpeiClientContext* context)
rdpei->frame.frameOffset = rdpei->currentFrameTime - rdpei->previousFrameTime;
}
rdpei_send_touch_event_pdu(callback, &rdpei->frame);
if ((error = rdpei_send_touch_event_pdu(callback, &rdpei->frame)))
{
WLog_ERR(TAG, "rdpei_send_touch_event_pdu failed with error %lu!", error);
return error;
}
rdpei->previousFrameTime = rdpei->currentFrameTime;
rdpei->frame.contactCount = 0;
return 1;
return error;
}
int rdpei_add_contact(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contact)
WIN32ERROR rdpei_add_contact(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contact)
{
RDPINPUT_CONTACT_POINT* contactPoint;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
@ -591,16 +682,17 @@ int rdpei_add_contact(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contac
LeaveCriticalSection(&rdpei->lock);
return 1;
return CHANNEL_RC_OK;
}
int rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y)
WIN32ERROR rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y, int* contactId)
{
int i;
int contactId = -1;
unsigned int i;
int contactIdlocal = -1;
RDPINPUT_CONTACT_DATA contact;
RDPINPUT_CONTACT_POINT* contactPoint = NULL;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
WIN32ERROR error = CHANNEL_RC_OK;
/* Create a new contact point in an empty slot */
@ -611,7 +703,7 @@ int rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y)
if (!contactPoint->active)
{
contactPoint->contactId = i;
contactId = contactPoint->contactId;
contactIdlocal = contactPoint->contactId;
contactPoint->externalId = externalId;
contactPoint->active = TRUE;
contactPoint->state = RDPINPUT_CONTACT_STATE_ENGAGED;
@ -619,7 +711,7 @@ int rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y)
}
}
if (contactId >= 0)
if (contactIdlocal >= 0)
{
ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA));
@ -628,25 +720,26 @@ int rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y)
contact.x = x;
contact.y = y;
contact.contactId = (UINT32) contactId;
contact.contactId = (UINT32) contactIdlocal;
contact.contactFlags |= CONTACT_FLAG_DOWN;
contact.contactFlags |= CONTACT_FLAG_INRANGE;
contact.contactFlags |= CONTACT_FLAG_INCONTACT;
context->AddContact(context, &contact);
error = context->AddContact(context, &contact);
}
return contactId;
*contactId = contactIdlocal;
return error;
}
int rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int y)
WIN32ERROR rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int y, int* contactId)
{
int i;
int contactId = -1;
unsigned int i;
int contactIdlocal = -1;
RDPINPUT_CONTACT_DATA contact;
RDPINPUT_CONTACT_POINT* contactPoint = NULL;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
WIN32ERROR error = CHANNEL_RC_OK;
for (i = 0; i < rdpei->maxTouchContacts; i++)
{
@ -657,12 +750,12 @@ int rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int y
if (contactPoint->externalId == externalId)
{
contactId = contactPoint->contactId;
contactIdlocal = contactPoint->contactId;
break;
}
}
if (contactId >= 0)
if (contactIdlocal >= 0)
{
ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA));
@ -671,25 +764,29 @@ int rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int y
contact.x = x;
contact.y = y;
contact.contactId = (UINT32) contactId;
contact.contactId = (UINT32) contactIdlocal;
contact.contactFlags |= CONTACT_FLAG_UPDATE;
contact.contactFlags |= CONTACT_FLAG_INRANGE;
contact.contactFlags |= CONTACT_FLAG_INCONTACT;
context->AddContact(context, &contact);
error = context->AddContact(context, &contact);
}
return contactId;
*contactId = contactIdlocal;
return error;
}
int rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y)
WIN32ERROR rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y, int* contactId)
{
int i;
int contactId = -1;
unsigned int i;
int contactIdlocal = -1;
int tempvalue;
RDPINPUT_CONTACT_DATA contact;
RDPINPUT_CONTACT_POINT* contactPoint = NULL;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle;
WIN32ERROR error;
for (i = 0; i < rdpei->maxTouchContacts; i++)
{
@ -700,27 +797,35 @@ int rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y)
if (contactPoint->externalId == externalId)
{
contactId = contactPoint->contactId;
contactIdlocal = contactPoint->contactId;
break;
}
}
if (contactId >= 0)
if (contactIdlocal >= 0)
{
ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA));
if ((contactPoint->lastX != x) && (contactPoint->lastY != y))
{
context->TouchUpdate(context, externalId, x, y);
if ((error = context->TouchUpdate(context, externalId, x, y, &tempvalue)))
{
WLog_ERR(TAG, "context->TouchUpdate failed with error %lu!", error);
return error;
}
}
contact.x = x;
contact.y = y;
contact.contactId = (UINT32) contactId;
contact.contactId = (UINT32) contactIdlocal;
contact.contactFlags |= CONTACT_FLAG_UP;
context->AddContact(context, &contact);
if ((error = context->AddContact(context, &contact)))
{
WLog_ERR(TAG, "context->AddContact failed with error %lu!", error);
return error;
}
contactPoint->externalId = 0;
contactPoint->active = FALSE;
@ -728,19 +833,20 @@ int rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y)
contactPoint->contactId = 0;
contactPoint->state = RDPINPUT_CONTACT_STATE_OUT_OF_RANGE;
}
*contactId = contactIdlocal;
return contactId;
return CHANNEL_RC_OK;
}
#ifdef STATIC_CHANNELS
#define DVCPluginEntry rdpei_DVCPluginEntry
#endif
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
int error = 0;
RDPEI_PLUGIN* rdpei;
RdpeiClientContext* context;
WIN32ERROR error;
RDPEI_PLUGIN* rdpei = NULL;
RdpeiClientContext* context = NULL;
rdpei = (RDPEI_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "rdpei");
@ -748,8 +854,12 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
size_t size;
rdpei = (RDPEI_PLUGIN*) malloc(sizeof(RDPEI_PLUGIN));
ZeroMemory(rdpei, sizeof(RDPEI_PLUGIN));
rdpei = (RDPEI_PLUGIN*) calloc(1, sizeof(RDPEI_PLUGIN));
if(!rdpei)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
rdpei->iface.Initialize = rdpei_plugin_initialize;
rdpei->iface.Connected = NULL;
@ -763,10 +873,21 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
rdpei->maxTouchContacts = 10;
size = rdpei->maxTouchContacts * sizeof(RDPINPUT_CONTACT_POINT);
rdpei->contactPoints = (RDPINPUT_CONTACT_POINT*) malloc(size);
ZeroMemory(rdpei->contactPoints, size);
rdpei->contactPoints = (RDPINPUT_CONTACT_POINT*) calloc(1, size);
if (!rdpei->contactPoints)
{
WLog_ERR(TAG, "calloc failed!");
error = CHANNEL_RC_NO_MEMORY;
goto error_out;
}
context = (RdpeiClientContext*) malloc(sizeof(RdpeiClientContext));
context = (RdpeiClientContext*) calloc(1, sizeof(RdpeiClientContext));
if (!context)
{
WLog_ERR(TAG, "calloc failed!");
error = CHANNEL_RC_NO_MEMORY;
goto error_out;
}
context->handle = (void*) rdpei;
context->GetVersion = rdpei_get_version;
@ -778,9 +899,20 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
rdpei->iface.pInterface = (void*) context;
error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpei", (IWTSPlugin*) rdpei);
if ((error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpei", (IWTSPlugin*) rdpei)))
{
WLog_ERR(TAG, "EntryPoints->RegisterPlugin failed with error %lu!", error);
error = CHANNEL_RC_NO_MEMORY;
goto error_out;
}
rdpei->context = context;
}
return CHANNEL_RC_OK;
error_out:
free(context);
free(rdpei->contactPoints);
free(rdpei);
return error;
}

View File

@ -4,6 +4,8 @@
*
* Copyright 2014 Thincast Technologies Gmbh.
* Copyright 2014 David FORT <contact@hardening-consulting.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -90,7 +92,7 @@ out_free:
return NULL;
}
int rdpei_server_init(RdpeiServerContext *context)
WIN32ERROR rdpei_server_init(RdpeiServerContext *context)
{
void *buffer = NULL;
DWORD bytesReturned;
@ -99,14 +101,13 @@ int rdpei_server_init(RdpeiServerContext *context)
priv->channelHandle = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, RDPEI_DVC_CHANNEL_NAME, WTS_CHANNEL_OPTION_DYNAMIC);
if (!priv->channelHandle)
{
fprintf(stderr, "%s: unable to open channel\n", __FUNCTION__);
return -1;
WLog_ERR(TAG, "WTSVirtualChannelOpenEx failed!");
return CHANNEL_RC_INITIALIZATION_ERROR;
}
if (!WTSVirtualChannelQuery(priv->channelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE)))
{
fprintf(stderr, "%s: error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)\n",
__FUNCTION__, bytesReturned);
WLog_ERR(TAG, "WTSVirtualChannelQuery failed or invalid invalid returned size(%d)!", bytesReturned);
if (buffer)
WTSFreeMemory(buffer);
goto out_close;
@ -114,11 +115,11 @@ int rdpei_server_init(RdpeiServerContext *context)
CopyMemory(&priv->eventHandle, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
return 0;
return CHANNEL_RC_OK;
out_close:
WTSVirtualChannelClose(priv->channelHandle);
return -1;
return CHANNEL_RC_INITIALIZATION_ERROR;
}
@ -149,10 +150,14 @@ HANDLE rdpei_server_get_event_handle(RdpeiServerContext *context)
}
static int read_cs_ready_message(RdpeiServerContext *context, wStream *s)
static WIN32ERROR read_cs_ready_message(RdpeiServerContext *context, wStream *s)
{
WIN32ERROR error = CHANNEL_RC_OK;
if (Stream_GetRemainingLength(s) < 10)
return -1;
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT32(s, context->protocolFlags);
Stream_Read_UINT32(s, context->clientVersion);
@ -164,26 +169,34 @@ static int read_cs_ready_message(RdpeiServerContext *context, wStream *s)
case RDPINPUT_PROTOCOL_V101:
break;
default:
fprintf(stderr, "%s: unhandled RPDEI protocol version 0x%x\n", __FUNCTION__, context->clientVersion);
WLog_ERR(TAG, "unhandled RPDEI protocol version 0x%x", context->clientVersion);
break;
}
if (context->onClientReady)
context->onClientReady(context);
return 0;
IFCALLRET(context->onClientReady, error, context);
if (error)
WLog_ERR(TAG, "context->onClientReady failed with error %lu", error);
return error;
}
static int read_touch_contact_data(RdpeiServerContext *context, wStream *s, RDPINPUT_CONTACT_DATA *contactData)
static WIN32ERROR read_touch_contact_data(RdpeiServerContext *context, wStream *s, RDPINPUT_CONTACT_DATA *contactData)
{
if (Stream_GetRemainingLength(s) < 1)
return -1;
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT8(s, contactData->contactId);
if (!rdpei_read_2byte_unsigned(s, &contactData->fieldsPresent) ||
!rdpei_read_4byte_signed(s, &contactData->x) ||
!rdpei_read_4byte_signed(s, &contactData->y) ||
!rdpei_read_4byte_unsigned(s, &contactData->contactFlags))
return -1;
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
if (contactData->fieldsPresent & CONTACT_DATA_CONTACTRECT_PRESENT)
{
@ -191,113 +204,144 @@ static int read_touch_contact_data(RdpeiServerContext *context, wStream *s, RDPI
!rdpei_read_2byte_signed(s, &contactData->contactRectTop) ||
!rdpei_read_2byte_signed(s, &contactData->contactRectRight) ||
!rdpei_read_2byte_signed(s, &contactData->contactRectBottom))
return -1;
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
}
if ((contactData->fieldsPresent & CONTACT_DATA_ORIENTATION_PRESENT) &&
!rdpei_read_4byte_unsigned(s, &contactData->orientation))
return -1;
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
if ((contactData->fieldsPresent & CONTACT_DATA_PRESSURE_PRESENT) &&
!rdpei_read_4byte_unsigned(s, &contactData->pressure))
return -1;
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
return 0;
return CHANNEL_RC_OK;
}
static int read_touch_frame(RdpeiServerContext *context, wStream *s, RDPINPUT_TOUCH_FRAME *frame)
static WIN32ERROR read_touch_frame(RdpeiServerContext *context, wStream *s, RDPINPUT_TOUCH_FRAME *frame)
{
int i;
RDPINPUT_CONTACT_DATA *contact;
WIN32ERROR error;
if (!rdpei_read_2byte_unsigned(s, &frame->contactCount) || !rdpei_read_8byte_unsigned(s, &frame->frameOffset))
return -1;
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
frame->contacts = contact = calloc(frame->contactCount, sizeof(RDPINPUT_CONTACT_DATA));
if (!frame->contacts)
return -1;
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
for (i = 0; i < frame->contactCount; i++, contact++)
{
if (read_touch_contact_data(context, s, contact) < 0)
if ((error = read_touch_contact_data(context, s, contact)))
{
WLog_ERR(TAG, "read_touch_contact_data failed with error %lu!", error);
frame->contactCount = i;
goto out_cleanup;
}
}
return 0;
out_cleanup:
touch_frame_reset(frame);
return -1;
return error;
}
}
return CHANNEL_RC_OK;
}
static int read_touch_event(RdpeiServerContext *context, wStream *s)
static WIN32ERROR read_touch_event(RdpeiServerContext *context, wStream *s)
{
UINT32 frameCount;
int i, ret;
int i;
RDPINPUT_TOUCH_EVENT *event = &context->priv->touchEvent;
RDPINPUT_TOUCH_FRAME *frame;
WIN32ERROR error = CHANNEL_RC_OK;
ret = -1;
if (!rdpei_read_4byte_unsigned(s, &event->encodeTime) || !rdpei_read_2byte_unsigned(s, &frameCount))
return -1;
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
event->frameCount = frameCount;
event->frames = frame = calloc(event->frameCount, sizeof(RDPINPUT_TOUCH_FRAME));
if (!event->frames)
return -1;
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
for (i = 0; i < frameCount; i++, frame++)
{
if (read_touch_frame(context, s, frame) < 0)
if ((error = read_touch_frame(context, s, frame)))
{
WLog_ERR(TAG, "read_touch_contact_data failed with error %lu!", error);
event->frameCount = i;
goto out_cleanup;
}
}
if (context->onTouchEvent)
context->onTouchEvent(context, event);
ret = 0;
IFCALLRET(context->onTouchEvent, error, context, event);
if (error)
WLog_ERR(TAG, "context->onTouchEvent failed with error %lu", error);
out_cleanup:
touch_event_reset(event);
return ret;
return error;
}
static int read_dismiss_hovering_contact(RdpeiServerContext *context, wStream *s) {
static WIN32ERROR read_dismiss_hovering_contact(RdpeiServerContext *context, wStream *s) {
BYTE contactId;
WIN32ERROR error = CHANNEL_RC_OK;
if (Stream_GetRemainingLength(s) < 1)
return -1;
{
WLog_ERR(TAG, "Not enought data!");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT8(s, contactId);
if (context->onTouchReleased)
context->onTouchReleased(context, contactId);
return 0;
IFCALLRET(context->onTouchReleased, error, context, contactId);
if (error)
WLog_ERR(TAG, "context->onTouchReleased failed with error %lu", error);
return error;
}
int rdpei_server_handle_messages(RdpeiServerContext *context) {
WIN32ERROR rdpei_server_handle_messages(RdpeiServerContext *context) {
DWORD bytesReturned;
RdpeiServerPrivate *priv = context->priv;
wStream *s = priv->inputStream;
WIN32ERROR error = CHANNEL_RC_OK;
if (!WTSVirtualChannelRead(priv->channelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned))
{
if (GetLastError() == ERROR_NO_DATA)
return -1;
return ERROR_READ_FAULT;
fprintf(stderr, "%s: channel connection closed\n", __FUNCTION__);
return 0;
WLog_DBG(TAG, "channel connection closed");
return CHANNEL_RC_OK;
}
priv->expectedBytes -= bytesReturned;
Stream_Seek(s, bytesReturned);
if (priv->expectedBytes)
return 1;
return CHANNEL_RC_OK;
Stream_SealLength(s);
Stream_SetPosition(s, 0);
@ -312,8 +356,8 @@ int rdpei_server_handle_messages(RdpeiServerContext *context) {
if (pduLen < RDPINPUT_HEADER_LENGTH)
{
fprintf(stderr, "%s: invalid pduLength %d\n", __FUNCTION__, pduLen);
return -1;
WLog_ERR(TAG, "invalid pduLength %d", pduLen);
return ERROR_INVALID_DATA;
}
priv->expectedBytes = pduLen - RDPINPUT_HEADER_LENGTH;
priv->waitingHeaders = FALSE;
@ -322,10 +366,10 @@ int rdpei_server_handle_messages(RdpeiServerContext *context) {
{
if (!Stream_EnsureCapacity(s, priv->expectedBytes))
{
fprintf(stderr, "%s: couldn't allocate memory for stream\n", __FUNCTION__);
return -1;
WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
return CHANNEL_RC_NO_MEMORY;
}
return 1;
return CHANNEL_RC_OK;
}
}
@ -335,56 +379,59 @@ int rdpei_server_handle_messages(RdpeiServerContext *context) {
case EVENTID_CS_READY:
if (priv->automataState != STATE_WAITING_CLIENT_READY)
{
fprintf(stderr, "%s: not expecting a CS_READY packet in this state(%d)\n", __FUNCTION__, (int)priv->automataState);
return 0;
WLog_ERR(TAG, "not expecting a CS_READY packet in this state(%d)", (int)priv->automataState);
return ERROR_INVALID_STATE;
}
if (read_cs_ready_message(context, s) < 0)
return 0;
if ((error = read_cs_ready_message(context, s)))
{
WLog_ERR(TAG, "read_cs_ready_message failed with error %lu", error);
return error;
}
break;
case EVENTID_TOUCH:
if (read_touch_event(context, s) < 0)
if ((error = read_touch_event(context, s)))
{
fprintf(stderr, "%s: error in touch event packet\n", __FUNCTION__);
return 0;
WLog_ERR(TAG, "read_touch_event failed with error %lu", error);
return error;
}
break;
case EVENTID_DISMISS_HOVERING_CONTACT:
if (read_dismiss_hovering_contact(context, s) < 0)
if ((error = read_dismiss_hovering_contact(context, s)))
{
fprintf(stderr, "%s: error reading read_dismiss_hovering_contact\n", __FUNCTION__);
return 0;
WLog_ERR(TAG, "read_dismiss_hovering_contact failed with error %lu", error);
return error;
}
break;
default:
fprintf(stderr, "%s: unexpected message type 0x%x\n", __FUNCTION__, priv->currentMsgType);
WLog_ERR(TAG, "unexpected message type 0x%x", priv->currentMsgType);
}
Stream_SetPosition(s, 0);
priv->waitingHeaders = TRUE;
priv->expectedBytes = RDPINPUT_HEADER_LENGTH;
return 1;
return error;
}
int rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version)
WIN32ERROR rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version)
{
ULONG written;
RdpeiServerPrivate *priv = context->priv;
if (priv->automataState != STATE_INITIAL)
{
fprintf(stderr, "%s: called from unexpected state %d\n", __FUNCTION__, priv->automataState);
return -1;
WLog_ERR(TAG, "called from unexpected state %d", (int)priv->automataState);
return ERROR_INVALID_STATE;
}
Stream_SetPosition(priv->outputStream, 0);
if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4))
{
fprintf(stderr, "%s: could not re-allocate memory for stream\n", __FUNCTION__);
return -1;
WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT16(priv->outputStream, EVENTID_SC_READY);
@ -394,15 +441,15 @@ int rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version)
if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream),
Stream_GetPosition(priv->outputStream), &written))
{
fprintf(stderr, "%s: error writing ready message\n", __FUNCTION__);
return -1;
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
return ERROR_INTERNAL_ERROR;
}
priv->automataState = STATE_WAITING_CLIENT_READY;
return 0;
return CHANNEL_RC_OK;
}
int rdpei_server_suspend(RdpeiServerContext *context)
WIN32ERROR rdpei_server_suspend(RdpeiServerContext *context)
{
ULONG written;
RdpeiServerPrivate *priv = context->priv;
@ -410,20 +457,20 @@ int rdpei_server_suspend(RdpeiServerContext *context)
switch (priv->automataState)
{
case STATE_SUSPENDED:
fprintf(stderr, "%s: already suspended\n", __FUNCTION__);
return 0;
WLog_ERR(TAG, "already suspended");
return CHANNEL_RC_OK;
case STATE_WAITING_FRAME:
break;
default:
fprintf(stderr, "%s: called from unexpected state %d\n", __FUNCTION__, priv->automataState);
return -1;
WLog_ERR(TAG, "called from unexpected state %d", (int)priv->automataState);
return ERROR_INVALID_STATE;
}
Stream_SetPosition(priv->outputStream, 0);
if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH))
{
fprintf(stderr, "%s: could not re-allocate memory for stream\n", __FUNCTION__);
return -1;
WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT16(priv->outputStream, EVENTID_SUSPEND_TOUCH);
@ -432,16 +479,16 @@ int rdpei_server_suspend(RdpeiServerContext *context)
if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream),
Stream_GetPosition(priv->outputStream), &written))
{
fprintf(stderr, "%s: error writing suspendTouch message\n", __FUNCTION__);
return -1;
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
return ERROR_INTERNAL_ERROR;
}
priv->automataState = STATE_SUSPENDED;
return 0;
return CHANNEL_RC_OK;
}
int rdpei_server_resume(RdpeiServerContext *context)
WIN32ERROR rdpei_server_resume(RdpeiServerContext *context)
{
ULONG written;
RdpeiServerPrivate *priv = context->priv;
@ -449,20 +496,20 @@ int rdpei_server_resume(RdpeiServerContext *context)
switch (priv->automataState)
{
case STATE_WAITING_FRAME:
fprintf(stderr, "%s: not suspended\n", __FUNCTION__);
return 0;
WLog_ERR(TAG, "not suspended");
return CHANNEL_RC_OK;
case STATE_SUSPENDED:
break;
default:
fprintf(stderr, "%s: called from unexpected state %d\n", __FUNCTION__, priv->automataState);
return -1;
WLog_ERR(TAG, "called from unexpected state %d", (int)priv->automataState);
return ERROR_INVALID_STATE;
}
Stream_SetPosition(priv->outputStream, 0);
if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH))
{
fprintf(stderr, "%s: couldn't allocate memory for stream\n", __FUNCTION__);
return -1;
WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT16(priv->outputStream, EVENTID_RESUME_TOUCH);
@ -471,11 +518,11 @@ int rdpei_server_resume(RdpeiServerContext *context)
if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream),
Stream_GetPosition(priv->outputStream), &written))
{
fprintf(stderr, "%s: error writing resumeTouch message\n", __FUNCTION__);
return -1;
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
return ERROR_INTERNAL_ERROR;
}
priv->automataState = STATE_WAITING_FRAME;
return 0;
return CHANNEL_RC_OK;
}

View File

@ -3,6 +3,8 @@
* Extended Input channel server-side implementation
*
* Copyright 2014 David Fort <contact@hardening-consulting.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@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,6 +25,10 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <freerdp/channels/log.h>
#define TAG CHANNELS_TAG("rdpei.server")
#endif /* FREERDP_CHANNEL_SERVER_RDPEI_MAIN_H_ */

View File

@ -604,17 +604,17 @@ int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtype)
if (evtype == XI_TouchBegin)
{
WLog_DBG(TAG, "TouchBegin: %d", touchId);
contactId = rdpei->TouchBegin(rdpei, touchId, x, y);
rdpei->TouchBegin(rdpei, touchId, x, y, &contactId);
}
else if (evtype == XI_TouchUpdate)
{
WLog_DBG(TAG, "TouchUpdate: %d", touchId);
contactId = rdpei->TouchUpdate(rdpei, touchId, x, y);
rdpei->TouchUpdate(rdpei, touchId, x, y, &contactId);
}
else if (evtype == XI_TouchEnd)
{
WLog_DBG(TAG, "TouchEnd: %d", touchId);
contactId = rdpei->TouchEnd(rdpei, touchId, x, y);
rdpei->TouchEnd(rdpei, touchId, x, y, &contactId);
}
return 0;

View File

@ -3,6 +3,8 @@
* Dynamic Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,6 +23,7 @@
#define FREERDP_CHANNEL_CLIENT_RDPEI_H
#include <freerdp/channels/rdpei.h>
#include <winpr/win32error.h>
/**
* Client Interface
@ -28,14 +31,15 @@
typedef struct _rdpei_client_context RdpeiClientContext;
typedef int (*pcRdpeiGetVersion)(RdpeiClientContext* context);typedef int (*pcRdpeiAddContact)(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contact);
typedef int (*pcRdpeiGetVersion)(RdpeiClientContext* context);
typedef WIN32ERROR (*pcRdpeiAddContact)(RdpeiClientContext* context, RDPINPUT_CONTACT_DATA* contact);
typedef int (*pcRdpeiTouchBegin)(RdpeiClientContext* context, int externalId, int x, int y);
typedef int (*pcRdpeiTouchUpdate)(RdpeiClientContext* context, int externalId, int x, int y);
typedef int (*pcRdpeiTouchEnd)(RdpeiClientContext* context, int externalId, int x, int y);
typedef WIN32ERROR (*pcRdpeiTouchBegin)(RdpeiClientContext* context, int externalId, int x, int y, int* contactId);
typedef WIN32ERROR (*pcRdpeiTouchUpdate)(RdpeiClientContext* context, int externalId, int x, int y, int* contactId);
typedef WIN32ERROR (*pcRdpeiTouchEnd)(RdpeiClientContext* context, int externalId, int x, int y, int* contactId);
typedef int (*pcRdpeiSuspendTouch)(RdpeiClientContext* context);
typedef int (*pcRdpeiResumeTouch)(RdpeiClientContext* context);
typedef WIN32ERROR (*pcRdpeiSuspendTouch)(RdpeiClientContext* context);
typedef WIN32ERROR (*pcRdpeiResumeTouch)(RdpeiClientContext* context);
struct _rdpei_client_context
{

View File

@ -4,6 +4,8 @@
*
* Copyright 2014 Thincast Technologies Gmbh.
* Copyright 2014 David FORT <contact@hardening-consulting.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -39,9 +41,9 @@ struct _rdpei_server_context
UINT32 protocolFlags;
/** callbacks that can be set by the user */
void (*onClientReady)(RdpeiServerContext *context);
void (*onTouchEvent)(RdpeiServerContext *context, RDPINPUT_TOUCH_EVENT *touchEvent);
void (*onTouchReleased)(RdpeiServerContext *context, BYTE contactId);
WIN32ERROR (*onClientReady)(RdpeiServerContext *context);
WIN32ERROR (*onTouchEvent)(RdpeiServerContext *context, RDPINPUT_TOUCH_EVENT *touchEvent);
WIN32ERROR (*onTouchReleased)(RdpeiServerContext *context, BYTE contactId);
void *user_data; /* user data, useful for callbacks */
};
@ -54,12 +56,12 @@ FREERDP_API RdpeiServerContext* rdpei_server_context_new(HANDLE vcm);
FREERDP_API void rdpei_server_context_reset(RdpeiServerContext *context);
FREERDP_API void rdpei_server_context_free(RdpeiServerContext* context);
FREERDP_API HANDLE rdpei_server_get_event_handle(RdpeiServerContext *context);
FREERDP_API int rdpei_server_init(RdpeiServerContext *context);
FREERDP_API int rdpei_server_handle_messages(RdpeiServerContext *context);
FREERDP_API WIN32ERROR rdpei_server_init(RdpeiServerContext *context);
FREERDP_API WIN32ERROR rdpei_server_handle_messages(RdpeiServerContext *context);
FREERDP_API int rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version);
FREERDP_API int rdpei_server_suspend(RdpeiServerContext *context);
FREERDP_API int rdpei_server_resume(RdpeiServerContext *context);
FREERDP_API WIN32ERROR rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version);
FREERDP_API WIN32ERROR rdpei_server_suspend(RdpeiServerContext *context);
FREERDP_API WIN32ERROR rdpei_server_resume(RdpeiServerContext *context);
#ifdef __cplusplus
}