mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2025-06-03 00:00:20 +00:00
channel echo hardend
This commit is contained in:
parent
2b3b999929
commit
0cfbc6648b
@ -3,6 +3,8 @@
|
|||||||
* Echo Virtual Channel Extension
|
* Echo Virtual Channel Extension
|
||||||
*
|
*
|
||||||
* Copyright 2013 Christian Hofstaedtler
|
* Copyright 2013 Christian Hofstaedtler
|
||||||
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -23,15 +25,14 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <winpr/crt.h>
|
#include <winpr/crt.h>
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
#include <winpr/cmdline.h>
|
|
||||||
|
|
||||||
#include <freerdp/addin.h>
|
|
||||||
|
|
||||||
#include "echo_main.h"
|
#include "echo_main.h"
|
||||||
|
#include <freerdp/channels/log.h>
|
||||||
|
|
||||||
|
#define TAG CHANNELS_TAG("echo.client")
|
||||||
|
|
||||||
typedef struct _ECHO_LISTENER_CALLBACK ECHO_LISTENER_CALLBACK;
|
typedef struct _ECHO_LISTENER_CALLBACK ECHO_LISTENER_CALLBACK;
|
||||||
struct _ECHO_LISTENER_CALLBACK
|
struct _ECHO_LISTENER_CALLBACK
|
||||||
@ -60,29 +61,26 @@ struct _ECHO_PLUGIN
|
|||||||
ECHO_LISTENER_CALLBACK* listener_callback;
|
ECHO_LISTENER_CALLBACK* listener_callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
|
static WIN32ERROR echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
|
||||||
{
|
{
|
||||||
int status;
|
|
||||||
ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*) pChannelCallback;
|
ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*) pChannelCallback;
|
||||||
BYTE* pBuffer = Stream_Pointer(data);
|
BYTE* pBuffer = Stream_Pointer(data);
|
||||||
UINT32 cbSize = Stream_GetRemainingLength(data);
|
UINT32 cbSize = Stream_GetRemainingLength(data);
|
||||||
|
|
||||||
/* echo back what we have received. ECHO does not have any message IDs. */
|
/* echo back what we have received. ECHO does not have any message IDs. */
|
||||||
status = callback->channel->Write(callback->channel, cbSize, pBuffer, NULL);
|
return callback->channel->Write(callback->channel, cbSize, pBuffer, NULL);
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int echo_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
static WIN32ERROR echo_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
||||||
{
|
{
|
||||||
ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*) pChannelCallback;
|
ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*) pChannelCallback;
|
||||||
|
|
||||||
free(callback);
|
free(callback);
|
||||||
|
|
||||||
return 0;
|
return CHANNEL_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
|
static WIN32ERROR echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
|
||||||
IWTSVirtualChannel* pChannel, BYTE* Data, int* pbAccept,
|
IWTSVirtualChannel* pChannel, BYTE* Data, int* pbAccept,
|
||||||
IWTSVirtualChannelCallback** ppCallback)
|
IWTSVirtualChannelCallback** ppCallback)
|
||||||
{
|
{
|
||||||
@ -92,7 +90,10 @@ static int echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallbac
|
|||||||
callback = (ECHO_CHANNEL_CALLBACK*) calloc(1, sizeof(ECHO_CHANNEL_CALLBACK));
|
callback = (ECHO_CHANNEL_CALLBACK*) calloc(1, sizeof(ECHO_CHANNEL_CALLBACK));
|
||||||
|
|
||||||
if (!callback)
|
if (!callback)
|
||||||
return -1;
|
{
|
||||||
|
WLog_ERR(TAG, "calloc failed!");
|
||||||
|
return CHANNEL_RC_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
callback->iface.OnDataReceived = echo_on_data_received;
|
callback->iface.OnDataReceived = echo_on_data_received;
|
||||||
callback->iface.OnClose = echo_on_close;
|
callback->iface.OnClose = echo_on_close;
|
||||||
@ -102,17 +103,20 @@ static int echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallbac
|
|||||||
|
|
||||||
*ppCallback = (IWTSVirtualChannelCallback*) callback;
|
*ppCallback = (IWTSVirtualChannelCallback*) callback;
|
||||||
|
|
||||||
return 0;
|
return CHANNEL_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
|
static WIN32ERROR echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
|
||||||
{
|
{
|
||||||
ECHO_PLUGIN* echo = (ECHO_PLUGIN*) pPlugin;
|
ECHO_PLUGIN* echo = (ECHO_PLUGIN*) pPlugin;
|
||||||
|
|
||||||
echo->listener_callback = (ECHO_LISTENER_CALLBACK*) calloc(1, sizeof(ECHO_LISTENER_CALLBACK));
|
echo->listener_callback = (ECHO_LISTENER_CALLBACK*) calloc(1, sizeof(ECHO_LISTENER_CALLBACK));
|
||||||
|
|
||||||
if (!echo->listener_callback)
|
if (!echo->listener_callback)
|
||||||
return -1;
|
{
|
||||||
|
WLog_ERR(TAG, "calloc failed!");
|
||||||
|
return CHANNEL_RC_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
echo->listener_callback->iface.OnNewChannelConnection = echo_on_new_channel_connection;
|
echo->listener_callback->iface.OnNewChannelConnection = echo_on_new_channel_connection;
|
||||||
echo->listener_callback->plugin = pPlugin;
|
echo->listener_callback->plugin = pPlugin;
|
||||||
@ -122,22 +126,22 @@ static int echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager
|
|||||||
(IWTSListenerCallback*) echo->listener_callback, NULL);
|
(IWTSListenerCallback*) echo->listener_callback, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int echo_plugin_terminated(IWTSPlugin* pPlugin)
|
static WIN32ERROR echo_plugin_terminated(IWTSPlugin* pPlugin)
|
||||||
{
|
{
|
||||||
ECHO_PLUGIN* echo = (ECHO_PLUGIN*) pPlugin;
|
ECHO_PLUGIN* echo = (ECHO_PLUGIN*) pPlugin;
|
||||||
|
|
||||||
free(echo);
|
free(echo);
|
||||||
|
|
||||||
return 0;
|
return CHANNEL_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef STATIC_CHANNELS
|
#ifdef STATIC_CHANNELS
|
||||||
#define DVCPluginEntry echo_DVCPluginEntry
|
#define DVCPluginEntry echo_DVCPluginEntry
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||||
{
|
{
|
||||||
int status = 0;
|
WIN32ERROR status = CHANNEL_RC_OK;
|
||||||
ECHO_PLUGIN* echo;
|
ECHO_PLUGIN* echo;
|
||||||
|
|
||||||
echo = (ECHO_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "echo");
|
echo = (ECHO_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "echo");
|
||||||
@ -147,7 +151,10 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
|||||||
echo = (ECHO_PLUGIN*) calloc(1, sizeof(ECHO_PLUGIN));
|
echo = (ECHO_PLUGIN*) calloc(1, sizeof(ECHO_PLUGIN));
|
||||||
|
|
||||||
if (!echo)
|
if (!echo)
|
||||||
return -1;
|
{
|
||||||
|
WLog_ERR(TAG, "calloc failed!");
|
||||||
|
return CHANNEL_RC_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
echo->iface.Initialize = echo_plugin_initialize;
|
echo->iface.Initialize = echo_plugin_initialize;
|
||||||
echo->iface.Connected = NULL;
|
echo->iface.Connected = NULL;
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
* Echo Virtual Channel Extension
|
* Echo Virtual Channel Extension
|
||||||
*
|
*
|
||||||
* Copyright 2014 Vic Lee
|
* Copyright 2014 Vic Lee
|
||||||
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -32,6 +34,9 @@
|
|||||||
#include <winpr/sysinfo.h>
|
#include <winpr/sysinfo.h>
|
||||||
|
|
||||||
#include <freerdp/server/echo.h>
|
#include <freerdp/server/echo.h>
|
||||||
|
#include <freerdp/channels/log.h>
|
||||||
|
|
||||||
|
#define TAG CHANNELS_TAG("echo.server")
|
||||||
|
|
||||||
typedef struct _echo_server
|
typedef struct _echo_server
|
||||||
{
|
{
|
||||||
@ -48,7 +53,7 @@ typedef struct _echo_server
|
|||||||
|
|
||||||
} echo_server;
|
} echo_server;
|
||||||
|
|
||||||
static BOOL echo_server_open_channel(echo_server* echo)
|
static WIN32ERROR echo_server_open_channel(echo_server* echo)
|
||||||
{
|
{
|
||||||
DWORD Error;
|
DWORD Error;
|
||||||
HANDLE hEvent;
|
HANDLE hEvent;
|
||||||
@ -59,8 +64,10 @@ static BOOL echo_server_open_channel(echo_server* echo)
|
|||||||
if (WTSQuerySessionInformationA(echo->context.vcm, WTS_CURRENT_SESSION,
|
if (WTSQuerySessionInformationA(echo->context.vcm, WTS_CURRENT_SESSION,
|
||||||
WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned) == FALSE)
|
WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned) == FALSE)
|
||||||
{
|
{
|
||||||
return FALSE;
|
WLog_ERR(TAG, "WTSQuerySessionInformationA failed!");
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
echo->SessionId = (DWORD) *pSessionId;
|
echo->SessionId = (DWORD) *pSessionId;
|
||||||
WTSFreeMemory(pSessionId);
|
WTSFreeMemory(pSessionId);
|
||||||
|
|
||||||
@ -85,7 +92,7 @@ static BOOL echo_server_open_channel(echo_server* echo)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return echo->echo_channel ? TRUE : FALSE;
|
return echo->echo_channel ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* echo_server_thread_func(void* arg)
|
static void* echo_server_thread_func(void* arg)
|
||||||
@ -98,10 +105,13 @@ static void* echo_server_thread_func(void* arg)
|
|||||||
HANDLE ChannelEvent;
|
HANDLE ChannelEvent;
|
||||||
DWORD BytesReturned = 0;
|
DWORD BytesReturned = 0;
|
||||||
echo_server* echo = (echo_server*) arg;
|
echo_server* echo = (echo_server*) arg;
|
||||||
|
WIN32ERROR error;
|
||||||
|
|
||||||
if (echo_server_open_channel(echo) == FALSE)
|
if ((error = echo_server_open_channel(echo)))
|
||||||
{
|
{
|
||||||
IFCALL(echo->context.OpenResult, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED);
|
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED);
|
||||||
|
WLog_ERR(TAG, "echo_server_open_channel failed with error %lu!", error);
|
||||||
|
ExitThread((DWORD)error);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,13 +137,17 @@ static void* echo_server_thread_func(void* arg)
|
|||||||
{
|
{
|
||||||
if (WaitForMultipleObjects(nCount, events, FALSE, 100) == WAIT_OBJECT_0)
|
if (WaitForMultipleObjects(nCount, events, FALSE, 100) == WAIT_OBJECT_0)
|
||||||
{
|
{
|
||||||
IFCALL(echo->context.OpenResult, &echo->context, ECHO_SERVER_OPEN_RESULT_CLOSED);
|
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_CLOSED);
|
||||||
|
if (error)
|
||||||
|
WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE)
|
if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE)
|
||||||
{
|
{
|
||||||
IFCALL(echo->context.OpenResult, &echo->context, ECHO_SERVER_OPEN_RESULT_ERROR);
|
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_ERROR);
|
||||||
|
if (error)
|
||||||
|
WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,12 +157,21 @@ static void* echo_server_thread_func(void* arg)
|
|||||||
|
|
||||||
if (ready)
|
if (ready)
|
||||||
{
|
{
|
||||||
IFCALL(echo->context.OpenResult, &echo->context, ECHO_SERVER_OPEN_RESULT_OK);
|
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_OK);
|
||||||
|
if (error)
|
||||||
|
WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s = Stream_New(NULL, 4096);
|
s = Stream_New(NULL, 4096);
|
||||||
|
if (!s)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "Stream_New failed!");
|
||||||
|
WTSVirtualChannelClose(echo->echo_channel);
|
||||||
|
ExitThread((DWORD)ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
while (ready)
|
while (ready)
|
||||||
{
|
{
|
||||||
@ -160,35 +183,60 @@ static void* echo_server_thread_func(void* arg)
|
|||||||
WTSVirtualChannelRead(echo->echo_channel, 0, NULL, 0, &BytesReturned);
|
WTSVirtualChannelRead(echo->echo_channel, 0, NULL, 0, &BytesReturned);
|
||||||
if (BytesReturned < 1)
|
if (BytesReturned < 1)
|
||||||
continue;
|
continue;
|
||||||
Stream_EnsureRemainingCapacity(s, BytesReturned);
|
if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
|
||||||
if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR) Stream_Buffer(s),
|
|
||||||
(ULONG) Stream_Capacity(s), &BytesReturned) == FALSE)
|
|
||||||
{
|
{
|
||||||
|
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||||
|
error = CHANNEL_RC_NO_MEMORY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFCALL(echo->context.Response, &echo->context, (BYTE *) Stream_Buffer(s), BytesReturned);
|
if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR) Stream_Buffer(s),
|
||||||
|
(ULONG) Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||||
|
error = ERROR_INTERNAL_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFCALLRET(echo->context.Response, error, &echo->context, (BYTE *) Stream_Buffer(s), BytesReturned);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "Response failed with error %lu!", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream_Free(s, TRUE);
|
Stream_Free(s, TRUE);
|
||||||
WTSVirtualChannelClose(echo->echo_channel);
|
WTSVirtualChannelClose(echo->echo_channel);
|
||||||
echo->echo_channel = NULL;
|
echo->echo_channel = NULL;
|
||||||
|
ExitThread((DWORD)error);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void echo_server_open(echo_server_context* context)
|
static WIN32ERROR echo_server_open(echo_server_context* context)
|
||||||
{
|
{
|
||||||
echo_server* echo = (echo_server*) context;
|
echo_server* echo = (echo_server*) context;
|
||||||
|
|
||||||
if (echo->thread == NULL)
|
if (echo->thread == NULL)
|
||||||
{
|
{
|
||||||
echo->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
if (!(echo->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
||||||
echo->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) echo_server_thread_func, (void*) echo, 0, NULL);
|
{
|
||||||
|
WLog_ERR(TAG, "CreateEvent failed!");
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(echo->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) echo_server_thread_func, (void*) echo, 0, NULL)))
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "CreateEvent failed!");
|
||||||
|
CloseHandle(echo->stopEvent);
|
||||||
|
echo->stopEvent = NULL;
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CHANNEL_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void echo_server_close(echo_server_context* context)
|
static WIN32ERROR echo_server_close(echo_server_context* context)
|
||||||
{
|
{
|
||||||
echo_server* echo = (echo_server*) context;
|
echo_server* echo = (echo_server*) context;
|
||||||
|
|
||||||
@ -201,6 +249,7 @@ static void echo_server_close(echo_server_context* context)
|
|||||||
echo->thread = NULL;
|
echo->thread = NULL;
|
||||||
echo->stopEvent = NULL;
|
echo->stopEvent = NULL;
|
||||||
}
|
}
|
||||||
|
return CHANNEL_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL echo_server_request(echo_server_context* context, const BYTE* buffer, UINT32 length)
|
static BOOL echo_server_request(echo_server_context* context, const BYTE* buffer, UINT32 length)
|
||||||
@ -216,10 +265,15 @@ echo_server_context* echo_server_context_new(HANDLE vcm)
|
|||||||
|
|
||||||
echo = (echo_server*) calloc(1, sizeof(echo_server));
|
echo = (echo_server*) calloc(1, sizeof(echo_server));
|
||||||
|
|
||||||
|
if (echo)
|
||||||
|
{
|
||||||
echo->context.vcm = vcm;
|
echo->context.vcm = vcm;
|
||||||
echo->context.Open = echo_server_open;
|
echo->context.Open = echo_server_open;
|
||||||
echo->context.Close = echo_server_close;
|
echo->context.Close = echo_server_close;
|
||||||
echo->context.Request = echo_server_request;
|
echo->context.Request = echo_server_request;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
WLog_ERR(TAG, "calloc failed!");
|
||||||
|
|
||||||
return (echo_server_context*) echo;
|
return (echo_server_context*) echo;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
* Echo Virtual Channel Extension
|
* Echo Virtual Channel Extension
|
||||||
*
|
*
|
||||||
* Copyright 2014 Vic Lee
|
* Copyright 2014 Vic Lee
|
||||||
|
* 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -21,6 +23,7 @@
|
|||||||
#define FREERDP_CHANNEL_ECHO_SERVER_H
|
#define FREERDP_CHANNEL_ECHO_SERVER_H
|
||||||
|
|
||||||
#include <freerdp/channels/wtsvc.h>
|
#include <freerdp/channels/wtsvc.h>
|
||||||
|
#include <winpr/win32error.h>
|
||||||
|
|
||||||
typedef enum ECHO_SERVER_OPEN_RESULT
|
typedef enum ECHO_SERVER_OPEN_RESULT
|
||||||
{
|
{
|
||||||
@ -32,12 +35,12 @@ typedef enum ECHO_SERVER_OPEN_RESULT
|
|||||||
|
|
||||||
typedef struct _echo_server_context echo_server_context;
|
typedef struct _echo_server_context echo_server_context;
|
||||||
|
|
||||||
typedef void (*psEchoServerOpen)(echo_server_context* context);
|
typedef WIN32ERROR (*psEchoServerOpen)(echo_server_context* context);
|
||||||
typedef void (*psEchoServerClose)(echo_server_context* context);
|
typedef WIN32ERROR (*psEchoServerClose)(echo_server_context* context);
|
||||||
typedef BOOL (*psEchoServerRequest)(echo_server_context* context, const BYTE* buffer, UINT32 length);
|
typedef BOOL (*psEchoServerRequest)(echo_server_context* context, const BYTE* buffer, UINT32 length);
|
||||||
|
|
||||||
typedef void (*psEchoServerOpenResult)(echo_server_context* context, ECHO_SERVER_OPEN_RESULT result);
|
typedef WIN32ERROR (*psEchoServerOpenResult)(echo_server_context* context, ECHO_SERVER_OPEN_RESULT result);
|
||||||
typedef void (*psEchoServerResponse)(echo_server_context* context, const BYTE* buffer, UINT32 length);
|
typedef WIN32ERROR (*psEchoServerResponse)(echo_server_context* context, const BYTE* buffer, UINT32 length);
|
||||||
|
|
||||||
struct _echo_server_context
|
struct _echo_server_context
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user