channel rdpei hardend
This commit is contained in:
parent
d7636d0e28
commit
6348e41479
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
touch_frame_reset(frame);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
out_cleanup:
|
||||
touch_frame_reset(frame);
|
||||
return -1;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user