add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
+if(WITH_SERVER_CHANNELS)
+ add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
+endif()
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
-set(OPTION_SERVER_DEFAULT OFF)
+set(OPTION_SERVER_DEFAULT ON)
define_channel_options(NAME "cliprdr" TYPE "static"
DESCRIPTION "Clipboard Virtual Channel Extension"
--- /dev/null
+# FreeRDP: A Remote Desktop Protocol Implementation
+# FreeRDP cmake build script
+#
+# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+define_channel_server("cliprdr")
+
+set(${MODULE_PREFIX}_SRCS
+ cliprdr_main.c
+ cliprdr_main.h)
+
+add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
+
+set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
+
+set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
+ MONOLITHIC ${MONOLITHIC_BUILD}
+ MODULE freerdp
+ MODULES freerdp-utils)
+
+target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
+
+set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")
--- /dev/null
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Clipboard Virtual Channel Extension
+ *
+ * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <winpr/crt.h>
+#include <winpr/stream.h>
+
+#include "cliprdr_main.h"
+
+/**
+ * Initialization Sequence\n
+ * Client Server\n
+ * | |\n
+ * |<----------------------Server Clipboard Capabilities PDU-----------------|\n
+ * |<-----------------------------Monitor Ready PDU--------------------------|\n
+ * |-----------------------Client Clipboard Capabilities PDU---------------->|\n
+ * |---------------------------Temporary Directory PDU---------------------->|\n
+ * |-------------------------------Format List PDU-------------------------->|\n
+ * |<--------------------------Format List Response PDU----------------------|\n
+ *
+ */
+
+static int cliprdr_server_send_capabilities(CliprdrServerContext* context)
+{
+ return 0;
+}
+
+static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context)
+{
+ return 0;
+}
+
+static int cliprdr_server_send_format_list_response(CliprdrServerContext* context)
+{
+ return 0;
+}
+
+static void* cliprdr_server_thread(void* arg)
+{
+ wStream* s;
+ DWORD status;
+ DWORD nCount;
+ void* buffer;
+ HANDLE events[8];
+ HANDLE ChannelEvent;
+ UINT32 BytesReturned;
+ CliprdrServerContext* context;
+
+ context = (CliprdrServerContext*) arg;
+
+ buffer = NULL;
+ BytesReturned = 0;
+ ChannelEvent = NULL;
+
+ s = Stream_New(NULL, 4096);
+
+ if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
+ {
+ if (BytesReturned == sizeof(HANDLE))
+ CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
+
+ WTSFreeMemory(buffer);
+ }
+
+ nCount = 0;
+ events[nCount++] = ChannelEvent;
+ events[nCount++] = context->priv->StopEvent;
+
+ while (1)
+ {
+ status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
+
+ if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
+ {
+ break;
+ }
+
+ if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
+ Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE)
+ {
+ if (BytesReturned == 0)
+ break;
+
+ Stream_EnsureRemainingCapacity(s, (int) BytesReturned);
+
+ if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
+ Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE)
+ {
+ break;
+ }
+ }
+ }
+
+ Stream_Free(s, TRUE);
+
+ return NULL;
+}
+
+static int cliprdr_server_start(CliprdrServerContext* context)
+{
+ context->priv->ChannelHandle = WTSVirtualChannelOpenEx(context->vcm, "cliprdr", 0);
+
+ if (!context->priv->ChannelHandle)
+ return -1;
+
+ context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ context->priv->Thread = CreateThread(NULL, 0,
+ (LPTHREAD_START_ROUTINE) cliprdr_server_thread, (void*) context, 0, NULL);
+
+ return 0;
+}
+
+static int cliprdr_server_stop(CliprdrServerContext* context)
+{
+ SetEvent(context->priv->StopEvent);
+
+ WaitForSingleObject(context->priv->Thread, INFINITE);
+ CloseHandle(context->priv->Thread);
+
+ return 0;
+}
+
+CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm)
+{
+ CliprdrServerContext* context;
+
+ context = (CliprdrServerContext*) malloc(sizeof(CliprdrServerContext));
+
+ if (context)
+ {
+ ZeroMemory(context, sizeof(CliprdrServerContext));
+
+ context->vcm = vcm;
+
+ context->Start = cliprdr_server_start;
+ context->Stop = cliprdr_server_stop;
+
+ context->SendCapabilities = cliprdr_server_send_capabilities;
+ context->SendMonitorReady = cliprdr_server_send_monitor_ready;
+ context->SendFormatListResponse = cliprdr_server_send_format_list_response;
+
+ context->priv = (CliprdrServerPrivate*) malloc(sizeof(CliprdrServerPrivate));
+
+ if (context->priv)
+ {
+ ZeroMemory(context->priv, sizeof(CliprdrServerPrivate));
+ }
+ }
+
+ return context;
+}
+
+void cliprdr_server_context_free(CliprdrServerContext* context)
+{
+ if (context)
+ {
+ if (context->priv)
+ {
+ free(context->priv);
+ }
+
+ free(context);
+ }
+}
--- /dev/null
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Clipboard Virtual Channel Extension
+ *
+ * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H
+#define FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H
+
+#include <winpr/crt.h>
+#include <winpr/synch.h>
+#include <winpr/thread.h>
+
+#include <freerdp/server/cliprdr.h>
+
+struct _cliprdr_server_private
+{
+ HANDLE Thread;
+ HANDLE StopEvent;
+ void* ChannelHandle;
+};
+
+#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H */
#include <freerdp/server/audin.h>
#include <freerdp/server/rdpsnd.h>
+#include <freerdp/server/cliprdr.h>
void freerdp_channels_dummy()
{
rdpsnd_server_context_new(NULL);
rdpsnd_server_context_free(NULL);
+
+ cliprdr_server_context_new(NULL);
+ cliprdr_server_context_free(NULL);
}
/**
vcm = (WTSVirtualChannelManager*) malloc(sizeof(WTSVirtualChannelManager));
- if (vcm != NULL)
+ if (vcm)
{
ZeroMemory(vcm, sizeof(WTSVirtualChannelManager));
BOOL result = FALSE;
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
ZeroMemory(fds, sizeof(fds));
+
switch (WtsVirtualClass)
{
case WTSVirtualFileHandle:
result = TRUE;
break;
+ case WTSVirtualEventHandle:
+ *ppBuffer = malloc(sizeof(HANDLE));
+ CopyMemory(*ppBuffer, &(channel->receive_event), sizeof(HANDLE));
+ *pBytesReturned = sizeof(void*);
+ result = TRUE;
+ break;
+
case WTSVirtualChannelReady:
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
{
if (settings->RemoteFxCodec)
{
wfc->tile = wf_image_new(wfc, 64, 64, 32, NULL);
- wfc->rfx_context = rfx_context_new();
+ wfc->rfx_context = rfx_context_new(FALSE);
}
if (settings->NSCodec)
if (instance->settings->RemoteFxCodec)
{
- rfx_context = (void*) rfx_context_new();
+ rfx_context = (void*) rfx_context_new(FALSE);
xfc->rfx_context = rfx_context;
}
{
WTSVirtualClientData,
WTSVirtualFileHandle,
+ WTSVirtualEventHandle,
WTSVirtualChannelReady
} WTS_VIRTUAL_CLASS;
#ifndef FREERDP_CHANNEL_CLIENT_CLIPRDR_H
#define FREERDP_CHANNEL_CLIENT_CLIPRDR_H
+#include <freerdp/types.h>
+
/**
* Client Interface
*/
int height;
BYTE* data;
int scanline;
-
BYTE quantIdxY;
BYTE quantIdxCb;
BYTE quantIdxCr;
{
RFX_STATE state;
+ BOOL encoder;
UINT16 flags;
UINT16 properties;
UINT16 width;
};
typedef struct _RFX_CONTEXT RFX_CONTEXT;
-FREERDP_API RFX_CONTEXT* rfx_context_new(void);
+FREERDP_API RFX_CONTEXT* rfx_context_new(BOOL encoder);
FREERDP_API void rfx_context_free(RFX_CONTEXT* context);
FREERDP_API void rfx_context_set_pixel_format(RFX_CONTEXT* context, RDP_PIXEL_FORMAT pixel_format);
FREERDP_API void rfx_context_reset(RFX_CONTEXT* context);
--- /dev/null
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Clipboard Virtual Channel Server Interface
+ *
+ * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FREERDP_CHANNEL_SERVER_CLIPRDR_H
+#define FREERDP_CHANNEL_SERVER_CLIPRDR_H
+
+#include <freerdp/api.h>
+#include <freerdp/types.h>
+#include <freerdp/channels/wtsvc.h>
+#include <freerdp/client/cliprdr.h>
+
+/**
+ * Server Interface
+ */
+
+typedef struct _cliprdr_server_context CliprdrServerContext;
+typedef struct _cliprdr_server_private CliprdrServerPrivate;
+
+typedef int (*psCliprdrStart)(CliprdrServerContext* context);
+typedef int (*psCliprdrStop)(CliprdrServerContext* context);
+
+typedef int (*psCliprdrSendCapabilities)(CliprdrServerContext* context);
+typedef int (*psCliprdrSendMonitorReady)(CliprdrServerContext* context);
+typedef int (*psCliprdrSendFormatListResponse)(CliprdrServerContext* context);
+
+struct _cliprdr_server_context
+{
+ WTSVirtualChannelManager* vcm;
+
+ psCliprdrStart Start;
+ psCliprdrStop Stop;
+
+ psCliprdrSendCapabilities SendCapabilities;
+ psCliprdrSendMonitorReady SendMonitorReady;
+ psCliprdrSendFormatListResponse SendFormatListResponse;
+
+ CliprdrServerPrivate* priv;
+};
+
+FREERDP_API CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm);
+FREERDP_API void cliprdr_server_context_free(CliprdrServerContext* context);
+
+#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_H */
}
}
-RFX_TILE* rfx_tile_new()
+RFX_TILE* rfx_decoder_tile_new()
{
RFX_TILE* tile = NULL;
return tile;
}
-void rfx_tile_free(RFX_TILE* tile)
+void rfx_decoder_tile_free(RFX_TILE* tile)
{
if (tile)
{
}
}
-RFX_CONTEXT* rfx_context_new(void)
+RFX_TILE* rfx_encoder_tile_new()
+{
+ RFX_TILE* tile = NULL;
+
+ tile = (RFX_TILE*) malloc(sizeof(RFX_TILE));
+
+ if (tile)
+ {
+ ZeroMemory(tile, sizeof(RFX_TILE));
+ }
+
+ return tile;
+}
+
+void rfx_encoder_tile_free(RFX_TILE* tile)
+{
+ if (tile)
+ {
+ free(tile);
+ }
+}
+
+RFX_CONTEXT* rfx_context_new(BOOL encoder)
{
HKEY hKey;
LONG status;
context = (RFX_CONTEXT*) malloc(sizeof(RFX_CONTEXT));
ZeroMemory(context, sizeof(RFX_CONTEXT));
+ context->encoder = encoder;
+
context->priv = (RFX_CONTEXT_PRIV*) malloc(sizeof(RFX_CONTEXT_PRIV));
ZeroMemory(context->priv, sizeof(RFX_CONTEXT_PRIV));
context->priv->TilePool = ObjectPool_New(TRUE);
- ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_tile_new;
ObjectPool_Object(context->priv->TilePool)->fnObjectInit = (OBJECT_INIT_FN) rfx_tile_init;
- ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_tile_free;
+
+ if (context->encoder)
+ {
+ ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_encoder_tile_new;
+ ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_encoder_tile_free;
+ }
+ else
+ {
+ ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_decoder_tile_new;
+ ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_decoder_tile_free;
+ }
/*
* align buffers to 16 byte boundary (needed for SSE/NEON instructions)
if (!context->numQuant)
{
context->numQuant = 1;
- context->quants = (UINT32*) rfx_default_quantization_values;
+ context->quants = (UINT32*) malloc(sizeof(rfx_default_quantization_values));
+ CopyMemory(context->quants, &rfx_default_quantization_values, sizeof(rfx_default_quantization_values));
context->quantIdxY = 0;
context->quantIdxCb = 0;
context->quantIdxCr = 0;
RFX_MESSAGE* message;
RFX_MESSAGE* messages;
- printf("rfx_encode_messages: numRects: %d maxDataSize: %d x: %d y: %d w: %d/%d h: %d/%d\n", numRects, maxDataSize,
- rects[0].x, rects[0].y, rects[0].width, width, rects[0].height, height);
-
message = rfx_encode_message(context, rects, numRects, data, width, height, scanline);
messages = rfx_split_message(context, message, numMessages, maxDataSize);
rfx_message_free(context, message);
gdi_register_graphics(instance->context->graphics);
- gdi->rfx_context = rfx_context_new();
+ gdi->rfx_context = rfx_context_new(FALSE);
gdi->nsc_context = nsc_context_new();
return 0;
int mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)\r
{\r
context->info = mf_info_get_instance();\r
- context->rfx_context = rfx_context_new();\r
+ context->rfx_context = rfx_context_new(TRUE);\r
context->rfx_context->mode = RLGR3;\r
context->rfx_context->width = client->settings->DesktopWidth;\r
context->rfx_context->height = client->settings->DesktopHeight;\r
void test_peer_context_new(freerdp_peer* client, testPeerContext* context)
{
- context->rfx_context = rfx_context_new();
+ context->rfx_context = rfx_context_new(TRUE);
context->rfx_context->mode = RLGR3;
context->rfx_context->width = SAMPLE_SERVER_DEFAULT_WIDTH;
context->rfx_context->height = SAMPLE_SERVER_DEFAULT_HEIGHT;
}
else
{
- wfi->rfx_context = rfx_context_new();
+ wfi->rfx_context = rfx_context_new(TRUE);
wfi->rfx_context->mode = RLGR3;
wfi->rfx_context->width = wfi->servscreen_width;
wfi->rfx_context->height = wfi->servscreen_height;
void xf_peer_context_new(freerdp_peer* client, xfPeerContext* context)
{
context->info = xf_info_init();
- context->rfx_context = rfx_context_new();
+ context->rfx_context = rfx_context_new(TRUE);
context->rfx_context->mode = RLGR3;
context->rfx_context->width = context->info->width;
context->rfx_context->height = context->info->height;