channels/cliprdr: implement initialization of server-side cliprdr

This commit is contained in:
Marc-André Moreau 2013-08-18 15:39:28 -04:00
parent bca442a477
commit af93bee5d2
5 changed files with 125 additions and 51 deletions

View File

@ -27,6 +27,7 @@
#include <string.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include <freerdp/types.h>
#include <freerdp/constants.h>
@ -76,6 +77,11 @@ void cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s)
Stream_Write_UINT32(s, dataLen);
Stream_SetPosition(s, pos);
#ifdef WITH_DEBUG_CLIPRDR
printf("Cliprdr Sending (%d bytes)\n", dataLen + 8);
winpr_HexDump(Stream_Buffer(s), dataLen + 8);
#endif
svc_plugin_send((rdpSvcPlugin*) cliprdr, s);
}
@ -206,6 +212,10 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s)
DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d",
CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen);
#ifdef WITH_DEBUG_CLIPRDR
winpr_HexDump(Stream_Buffer(s), dataLen + 8);
#endif
switch (msgType)
{
case CB_CLIP_CAPS:

View File

@ -40,6 +40,28 @@
*
*/
/**
* Data Transfer Sequences\n
* Shared Local\n
* Clipboard Owner Clipboard Owner\n
* | |\n
* |-------------------------------------------------------------------------|\n _
* |-------------------------------Format List PDU-------------------------->|\n |
* |<--------------------------Format List Response PDU----------------------|\n _| Copy Sequence
* |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n
* |-------------------------------------------------------------------------|\n
* |-------------------------------------------------------------------------|\n _
* |<--------------------------Format Data Request PDU-----------------------|\n | Paste Sequence Palette,
* |---------------------------Format Data Response PDU--------------------->|\n _| Metafile, File List Data
* |-------------------------------------------------------------------------|\n
* |-------------------------------------------------------------------------|\n _
* |<------------------------Format Contents Request PDU---------------------|\n | Paste Sequence
* |-------------------------Format Contents Response PDU------------------->|\n _| File Stream Data
* |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n
* |-------------------------------------------------------------------------|\n
*
*/
static int cliprdr_server_send_capabilities(CliprdrServerContext* context)
{
wStream* s;
@ -51,14 +73,14 @@ static int cliprdr_server_send_capabilities(CliprdrServerContext* context)
header.msgType = CB_CLIP_CAPS;
header.msgFlags = 0;
header.dataLen = 24;
header.dataLen = 16;
generalFlags = 0;
if (context->priv->UseLongFormatNames)
generalFlags |= CB_USE_LONG_FORMAT_NAMES;
s = Stream_New(NULL, header.dataLen);
s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH);
Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */
Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
@ -91,9 +113,9 @@ static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context)
header.msgType = CB_MONITOR_READY;
header.msgFlags = 0;
header.dataLen = 8;
header.dataLen = 0;
s = Stream_New(NULL, header.dataLen);
s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH);
Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */
Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
@ -110,6 +132,28 @@ static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context)
static int cliprdr_server_send_format_list_response(CliprdrServerContext* context)
{
wStream* s;
BOOL status;
CLIPRDR_HEADER header;
printf("CliprdrServerSendFormatListResponse\n");
header.msgType = CB_FORMAT_LIST_RESPONSE;
header.msgFlags = CB_RESPONSE_OK;
header.dataLen = 0;
s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH);
Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */
Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
Stream_Write_UINT32(s, header.dataLen); /* dataLen (4 bytes) */
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
@ -163,6 +207,21 @@ int cliprdr_wcslen(const WCHAR* str, const WCHAR* end)
return (p - str);
}
static void cliprdr_free_format_list(UINT32 count, CLIPRDR_FORMAT_NAME* formatNames)
{
int i;
if (formatNames)
{
for (i = 0; i < count; i++)
{
free(formatNames[i].name);
}
free(formatNames);
}
}
static int cliprdr_server_receive_long_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
int i;
@ -171,11 +230,13 @@ static int cliprdr_server_receive_long_format_list(CliprdrServerContext* context
int position;
position = Stream_GetPosition(s);
end = (WCHAR*) &(Stream_Buffer(s)[Stream_Length(s)]);
winpr_HexDump(Stream_Buffer(s), Stream_Length(s));
Stream_SetPosition(s, Stream_Length(s));
end = (WCHAR*) Stream_Pointer(s);
Stream_SetPosition(s, position);
cliprdr_free_format_list(context->priv->ClientFormatNameCount, context->priv->ClientFormatNames);
context->priv->ClientFormatNameCount = 0;
context->priv->ClientFormatNames = NULL;
while (Stream_GetRemainingLength(s) >= 6)
{
@ -188,7 +249,7 @@ static int cliprdr_server_receive_long_format_list(CliprdrServerContext* context
Stream_Seek(s, (length + 1) * 2); /* wszFormatName */
context->priv->ClientFormatNameCount = 0;
context->priv->ClientFormatNameCount++;
}
context->priv->ClientFormatNames = (CLIPRDR_FORMAT_NAME*)
@ -235,31 +296,27 @@ static int cliprdr_server_receive_format_list(CliprdrServerContext* context, wSt
status = cliprdr_server_receive_short_format_list(context, s, header);
}
cliprdr_server_send_format_list_response(context);
return status;
}
static int cliprdr_server_receive_pdu(CliprdrServerContext* context, wStream* s)
static int cliprdr_server_receive_pdu(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
CLIPRDR_HEADER header;
Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */
Stream_Read_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
Stream_Read_UINT32(s, header.dataLen); /* dataLen (4 bytes) */
printf("CliprdrServerReceivePdu: msgType: %d msgFlags: 0x%08X dataLen: %d\n",
header.msgType, header.msgFlags, header.dataLen);
header->msgType, header->msgFlags, header->dataLen);
switch (header.msgType)
switch (header->msgType)
{
case CB_CLIP_CAPS:
cliprdr_server_receive_capabilities(context, s, &header);
cliprdr_server_receive_capabilities(context, s, header);
break;
case CB_TEMP_DIRECTORY:
break;
case CB_FORMAT_LIST:
cliprdr_server_receive_format_list(context, s, &header);
cliprdr_server_receive_format_list(context, s, header);
break;
case CB_FORMAT_LIST_RESPONSE:
@ -284,7 +341,7 @@ static int cliprdr_server_receive_pdu(CliprdrServerContext* context, wStream* s)
break;
default:
printf("Unexpected clipboard PDU type: %d\n", header.msgType);
printf("Unexpected clipboard PDU type: %d\n", header->msgType);
break;
}
@ -297,9 +354,11 @@ static void* cliprdr_server_thread(void* arg)
DWORD status;
DWORD nCount;
void* buffer;
int position;
HANDLE events[8];
HANDLE ChannelEvent;
UINT32 BytesReturned;
CLIPRDR_HEADER header;
CliprdrServerContext* context;
context = (CliprdrServerContext*) arg;
@ -322,8 +381,8 @@ static void* cliprdr_server_thread(void* arg)
events[nCount++] = ChannelEvent;
events[nCount++] = context->priv->StopEvent;
context->SendCapabilities(context);
context->SendMonitorReady(context);
cliprdr_server_send_capabilities(context);
cliprdr_server_send_monitor_ready(context);
while (1)
{
@ -335,26 +394,36 @@ static void* cliprdr_server_thread(void* arg)
}
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE)
Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
{
if (BytesReturned)
Stream_Seek(s, BytesReturned);
}
else
{
if (!BytesReturned)
break;
Stream_EnsureRemainingCapacity(s, BytesReturned);
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE)
{
break;
}
Stream_Seek(s, BytesReturned);
}
Stream_SealLength(s);
Stream_SetPosition(s, 0);
if (Stream_GetPosition(s) >= CLIPRDR_HEADER_LENGTH)
{
position = Stream_GetPosition(s);
Stream_SetPosition(s, 0);
cliprdr_server_receive_pdu(context, s);
Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */
Stream_Read_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
Stream_Read_UINT32(s, header.dataLen); /* dataLen (4 bytes) */
Stream_SetPosition(s, position);
if (Stream_GetPosition(s) >= (header.dataLen + CLIPRDR_HEADER_LENGTH))
{
Stream_SealLength(s);
Stream_SetPosition(s, CLIPRDR_HEADER_LENGTH);
cliprdr_server_receive_pdu(context, s, &header);
Stream_SetPosition(s, 0);
}
}
}
Stream_Free(s, TRUE);
@ -402,10 +471,6 @@ CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* 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)
@ -413,6 +478,9 @@ CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm)
ZeroMemory(context->priv, sizeof(CliprdrServerPrivate));
context->priv->UseLongFormatNames = TRUE;
context->priv->StreamFileClipEnabled = TRUE;
context->priv->FileClipNoFilePaths = TRUE;
context->priv->CanLockClipData = TRUE;
}
}

View File

@ -26,6 +26,8 @@
#include <freerdp/server/cliprdr.h>
#define CLIPRDR_HEADER_LENGTH 8
struct _CLIPRDR_HEADER
{
UINT16 msgType;
@ -39,10 +41,12 @@ struct _cliprdr_server_private
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
BOOL UseLongFormatNames;
BOOL StreamFileClipEnabled;
BOOL FileClipNoFilePaths;
BOOL CanLockClipData;
UINT32 ClientFormatNameCount;
CLIPRDR_FORMAT_NAME* ClientFormatNames;
};

View File

@ -749,7 +749,7 @@ BOOL WTSVirtualChannelRead(
item = (wts_data_item*) list_peek(channel->receive_queue);
if (item == NULL)
if (!item)
{
ResetEvent(channel->receive_event);
*pBytesRead = 0;
@ -771,7 +771,7 @@ BOOL WTSVirtualChannelRead(
ReleaseMutex(channel->mutex);
CopyMemory(Buffer, item->buffer, item->length);
wts_data_item_free(item) ;
wts_data_item_free(item);
return TRUE;
}

View File

@ -35,10 +35,6 @@ 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;
@ -46,10 +42,6 @@ struct _cliprdr_server_context
psCliprdrStart Start;
psCliprdrStop Stop;
psCliprdrSendCapabilities SendCapabilities;
psCliprdrSendMonitorReady SendMonitorReady;
psCliprdrSendFormatListResponse SendFormatListResponse;
CliprdrServerPrivate* priv;
};