Merge branch 'xrdp-ng' of github.com:awakecoding/FreeRDP

This commit is contained in:
Marc-André Moreau 2013-09-16 16:46:33 -04:00
commit a26db7a980
118 changed files with 8389 additions and 1189 deletions

View File

@ -284,6 +284,7 @@ if(NOT IOS AND NOT ANDROID)
endif()
if(UNIX OR CYGWIN)
check_include_files(sys/eventfd.h HAVE_AIO_H)
check_include_files(sys/eventfd.h HAVE_EVENTFD_H)
check_include_files(sys/timerfd.h HAVE_TIMERFD_H)
set(X11_FEATURE_TYPE "RECOMMENDED")

View File

@ -78,7 +78,7 @@ static void audin_server_send_version(audin_server* audin, wStream* s)
{
Stream_Write_UINT8(s, MSG_SNDIN_VERSION);
Stream_Write_UINT32(s, 1); /* Version (4 bytes) */
WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
}
static BOOL audin_server_recv_version(audin_server* audin, wStream* s, UINT32 length)
@ -130,7 +130,7 @@ static void audin_server_send_formats(audin_server* audin, wStream* s)
}
}
WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
}
static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length)
@ -166,6 +166,7 @@ static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 le
Stream_Read_UINT16(s, audin->context.client_formats[i].nBlockAlign);
Stream_Read_UINT16(s, audin->context.client_formats[i].wBitsPerSample);
Stream_Read_UINT16(s, audin->context.client_formats[i].cbSize);
if (audin->context.client_formats[i].cbSize > 0)
{
Stream_Seek(s, audin->context.client_formats[i].cbSize);
@ -201,7 +202,7 @@ static void audin_server_send_open(audin_server* audin, wStream* s)
Stream_Write_UINT16(s, 16); /* wBitsPerSample */
Stream_Write_UINT16(s, 0); /* cbSize */
WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
}
static BOOL audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32 length)
@ -283,10 +284,10 @@ static void* audin_server_thread_func(void* arg)
void* buffer;
BYTE MessageId;
BOOL ready = FALSE;
UINT32 bytes_returned = 0;
DWORD BytesReturned = 0;
audin_server* audin = (audin_server*) arg;
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == TRUE)
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualFileHandle, &buffer, &BytesReturned) == TRUE)
{
fd = *((void**) buffer);
WTSFreeMemory(buffer);
@ -303,7 +304,7 @@ static void* audin_server_thread_func(void* arg)
if (WaitForSingleObject(audin->stopEvent, 0) == WAIT_OBJECT_0)
break;
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &bytes_returned) == FALSE)
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE)
break;
ready = *((BOOL*) buffer);
@ -330,46 +331,48 @@ static void* audin_server_thread_func(void* arg)
Stream_SetPosition(s, 0);
if (WTSVirtualChannelRead(audin->audin_channel, 0, Stream_Buffer(s),
Stream_Capacity(s), &bytes_returned) == FALSE)
if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s),
Stream_Capacity(s), &BytesReturned) == FALSE)
{
if (bytes_returned == 0)
if (BytesReturned == 0)
break;
Stream_EnsureRemainingCapacity(s, (int) bytes_returned);
Stream_EnsureRemainingCapacity(s, BytesReturned);
if (WTSVirtualChannelRead(audin->audin_channel, 0, Stream_Buffer(s),
Stream_Capacity(s), &bytes_returned) == FALSE)
if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s),
Stream_Capacity(s), &BytesReturned) == FALSE)
{
break;
}
}
if (bytes_returned < 1)
if (BytesReturned < 1)
continue;
Stream_Read_UINT8(s, MessageId);
bytes_returned--;
BytesReturned--;
switch (MessageId)
{
case MSG_SNDIN_VERSION:
if (audin_server_recv_version(audin, s, bytes_returned))
if (audin_server_recv_version(audin, s, BytesReturned))
audin_server_send_formats(audin, s);
break;
case MSG_SNDIN_FORMATS:
if (audin_server_recv_formats(audin, s, bytes_returned))
if (audin_server_recv_formats(audin, s, BytesReturned))
audin_server_send_open(audin, s);
break;
case MSG_SNDIN_OPEN_REPLY:
audin_server_recv_open_reply(audin, s, bytes_returned);
audin_server_recv_open_reply(audin, s, BytesReturned);
break;
case MSG_SNDIN_DATA_INCOMING:
break;
case MSG_SNDIN_DATA:
audin_server_recv_data(audin, s, bytes_returned);
audin_server_recv_data(audin, s, BytesReturned);
break;
case MSG_SNDIN_FORMATCHANGE:
@ -394,7 +397,7 @@ static BOOL audin_server_open(audin_server_context* context)
if (!audin->thread)
{
audin->audin_channel = WTSVirtualChannelOpenEx(context->vcm, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
audin->audin_channel = WTSVirtualChannelManagerOpenEx(context->vcm, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
if (!audin->audin_channel)
return FALSE;

View File

@ -21,3 +21,6 @@ if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -1,7 +1,7 @@
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"

View File

@ -18,7 +18,6 @@
define_channel_client("cliprdr")
set(${MODULE_PREFIX}_SRCS
cliprdr_constants.h
cliprdr_format.c
cliprdr_format.h
cliprdr_main.c

View File

@ -1,58 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Clipboard Virtual Channel
*
* Copyright 2009-2011 Jay Sorg
* Copyright 2010-2011 Vic Lee
*
* 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 __CLIPRDR_CONSTANTS
#define __CLIPRDR_CONSTANTS
/* CLIPRDR_HEADER.msgType */
#define CB_MONITOR_READY 0x0001
#define CB_FORMAT_LIST 0x0002
#define CB_FORMAT_LIST_RESPONSE 0x0003
#define CB_FORMAT_DATA_REQUEST 0x0004
#define CB_FORMAT_DATA_RESPONSE 0x0005
#define CB_TEMP_DIRECTORY 0x0006
#define CB_CLIP_CAPS 0x0007
#define CB_FILECONTENTS_REQUEST 0x0008
#define CB_FILECONTENTS_RESPONSE 0x0009
#define CB_LOCK_CLIPDATA 0x000A
#define CB_UNLOCK_CLIPDATA 0x000B
/* CLIPRDR_HEADER.msgFlags */
#define CB_RESPONSE_OK 0x0001
#define CB_RESPONSE_FAIL 0x0002
#define CB_ASCII_NAMES 0x0004
/* CLIPRDR_CAPS_SET.capabilitySetType */
#define CB_CAPSTYPE_GENERAL 0x0001
/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */
#define CB_CAPSTYPE_GENERAL_LEN 12
/* CLIPRDR_GENERAL_CAPABILITY.version */
#define CB_CAPS_VERSION_1 0x00000001
#define CB_CAPS_VERSION_2 0x00000002
/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
#define CB_USE_LONG_FORMAT_NAMES 0x00000002
#define CB_STREAM_FILECLIP_ENABLED 0x00000004
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008
#define CB_CAN_LOCK_CLIPDATA 0x00000010
#endif /* __CLIPRDR_CONSTANTS */

View File

@ -34,7 +34,6 @@
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/cliprdr.h>
#include "cliprdr_constants.h"
#include "cliprdr_main.h"
#include "cliprdr_format.h"

View File

@ -27,13 +27,13 @@
#include <string.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/cliprdr.h>
#include "cliprdr_constants.h"
#include "cliprdr_main.h"
#include "cliprdr_format.h"
@ -77,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);
}
@ -207,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

@ -25,14 +25,6 @@
#include <freerdp/utils/debug.h>
struct _CLIPRDR_FORMAT_NAME
{
UINT32 id;
char* name;
int length;
};
typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME;
struct cliprdr_plugin
{
rdpSvcPlugin plugin;

View File

@ -0,0 +1,35 @@
# 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")

View File

@ -0,0 +1,536 @@
/**
* 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/print.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
*
*/
/**
* 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;
BOOL status;
UINT32 generalFlags;
CLIPRDR_HEADER header;
printf("CliprdrServerSendCapabilities\n");
header.msgType = CB_CLIP_CAPS;
header.msgFlags = 0;
header.dataLen = 16;
generalFlags = 0;
if (context->priv->UseLongFormatNames)
generalFlags |= CB_USE_LONG_FORMAT_NAMES;
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_Write_UINT16(s, 1); /* cCapabilitiesSets (2 bytes) */
Stream_Write_UINT16(s, 0); /* pad1 (2 bytes) */
Stream_Write_UINT16(s, CB_CAPSTYPE_GENERAL); /* capabilitySetType (2 bytes) */
Stream_Write_UINT16(s, CB_CAPSTYPE_GENERAL_LEN); /* lengthCapability (2 bytes) */
Stream_Write_UINT32(s, CB_CAPS_VERSION_2); /* version (4 bytes) */
Stream_Write_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context)
{
wStream* s;
BOOL status;
CLIPRDR_HEADER header;
printf("CliprdrServerSendMonitorReady\n");
header.msgType = CB_MONITOR_READY;
header.msgFlags = 0;
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, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
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, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int cliprdr_server_receive_capabilities(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
UINT32 version;
UINT32 generalFlags;
UINT16 cCapabilitiesSets;
UINT16 capabilitySetType;
UINT16 lengthCapability;
Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */
Stream_Seek_UINT16(s); /* pad1 (2 bytes) */
Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */
Stream_Read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */
Stream_Read_UINT32(s, version); /* version (4 bytes) */
Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
if (generalFlags & CB_USE_LONG_FORMAT_NAMES)
context->priv->UseLongFormatNames = TRUE;
if (generalFlags & CB_STREAM_FILECLIP_ENABLED)
context->priv->StreamFileClipEnabled = TRUE;
if (generalFlags & CB_FILECLIP_NO_FILE_PATHS)
context->priv->FileClipNoFilePaths = TRUE;
if (generalFlags & CB_CAN_LOCK_CLIPDATA)
context->priv->CanLockClipData = TRUE;
return 0;
}
static int cliprdr_server_receive_temporary_directory(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
WCHAR* wszTempDir;
if (Stream_GetRemainingLength(s) < 520)
return -1;
wszTempDir = (WCHAR*) Stream_Pointer(s);
if (wszTempDir[260] != 0)
return -1;
ConvertFromUnicode(CP_UTF8, 0, wszTempDir, -1,
&(context->priv->ClientTemporaryDirectory), 0, NULL, NULL);
printf("ClientTemporaryDirectory: %s\n", context->priv->ClientTemporaryDirectory);
return 0;
}
int cliprdr_wcslen(const WCHAR* str, const WCHAR* end)
{
WCHAR* p = (WCHAR*) str;
if (!p)
return -1;
while (*p)
{
if (p == end)
return -1;
p++;
}
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;
WCHAR* end;
int length;
int position;
printf("%s\n", __FUNCTION__);
position = Stream_GetPosition(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)
{
Stream_Seek(s, 4); /* formatId (4 bytes) */
length = cliprdr_wcslen((WCHAR*) Stream_Pointer(s), end);
if (length < 0)
return -1;
Stream_Seek(s, (length + 1) * 2); /* wszFormatName */
context->priv->ClientFormatNameCount++;
}
context->priv->ClientFormatNames = (CLIPRDR_FORMAT_NAME*)
malloc(sizeof(CLIPRDR_FORMAT_NAME) * context->priv->ClientFormatNameCount);
Stream_SetPosition(s, position);
for (i = 0; i < context->priv->ClientFormatNameCount; i++)
{
Stream_Read_UINT32(s, context->priv->ClientFormatNames[i].id); /* formatId (4 bytes) */
length = cliprdr_wcslen((WCHAR*) Stream_Pointer(s), end);
context->priv->ClientFormatNames[i].name = NULL;
if (length)
{
context->priv->ClientFormatNames[i].length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
-1, &(context->priv->ClientFormatNames[i].name), 0, NULL, NULL) - 1;
}
else
{
context->priv->ClientFormatNames[i].length = 0;
}
Stream_Seek(s, (length + 1) * 2); /* wszFormatName */
}
for (i = 0; i < context->priv->ClientFormatNameCount; i++)
{
printf("Format %d: Id: 0x%04X Name: %s Length: %d\n", i,
context->priv->ClientFormatNames[i].id,
context->priv->ClientFormatNames[i].name,
context->priv->ClientFormatNames[i].length);
}
return 0;
}
static int cliprdr_server_receive_short_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
printf("%s: unimplemented\n", __FUNCTION__);
return 0;
}
static int cliprdr_server_receive_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
int status;
if (context->priv->UseLongFormatNames)
{
status = cliprdr_server_receive_long_format_list(context, s, header);
}
else
{
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, CLIPRDR_HEADER* header)
{
printf("CliprdrServerReceivePdu: msgType: %d msgFlags: 0x%08X dataLen: %d\n",
header->msgType, header->msgFlags, header->dataLen);
switch (header->msgType)
{
case CB_CLIP_CAPS:
cliprdr_server_receive_capabilities(context, s, header);
break;
case CB_TEMP_DIRECTORY:
cliprdr_server_receive_temporary_directory(context, s, header);
break;
case CB_FORMAT_LIST:
cliprdr_server_receive_format_list(context, s, header);
break;
case CB_FORMAT_LIST_RESPONSE:
break;
case CB_LOCK_CLIPDATA:
break;
case CB_UNLOCK_CLIPDATA:
break;
case CB_FORMAT_DATA_REQUEST:
break;
case CB_FORMAT_DATA_RESPONSE:
break;
case CB_FILECONTENTS_REQUEST:
break;
case CB_FILECONTENTS_RESPONSE:
break;
default:
printf("Unexpected clipboard PDU type: %d\n", header->msgType);
break;
}
return 0;
}
static void* cliprdr_server_thread(void* arg)
{
wStream* s;
DWORD status;
DWORD nCount;
void* buffer;
int position;
HANDLE events[8];
HANDLE ChannelEvent;
DWORD BytesReturned;
CLIPRDR_HEADER header;
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;
cliprdr_server_send_capabilities(context);
cliprdr_server_send_monitor_ready(context);
while (1)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
{
if (BytesReturned)
Stream_Seek(s, BytesReturned);
}
else
{
Stream_EnsureRemainingCapacity(s, BytesReturned);
}
if (Stream_GetPosition(s) >= CLIPRDR_HEADER_LENGTH)
{
position = Stream_GetPosition(s);
Stream_SetPosition(s, 0);
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);
return NULL;
}
static int cliprdr_server_start(CliprdrServerContext* context)
{
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(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->priv = (CliprdrServerPrivate*) malloc(sizeof(CliprdrServerPrivate));
if (context->priv)
{
ZeroMemory(context->priv, sizeof(CliprdrServerPrivate));
context->priv->UseLongFormatNames = TRUE;
context->priv->StreamFileClipEnabled = TRUE;
context->priv->FileClipNoFilePaths = TRUE;
context->priv->CanLockClipData = TRUE;
}
}
return context;
}
void cliprdr_server_context_free(CliprdrServerContext* context)
{
if (context)
{
if (context->priv)
{
free(context->priv);
}
free(context);
}
}

View File

@ -0,0 +1,56 @@
/**
* 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>
#define CLIPRDR_HEADER_LENGTH 8
struct _CLIPRDR_HEADER
{
UINT16 msgType;
UINT16 msgFlags;
UINT32 dataLen;
};
typedef struct _CLIPRDR_HEADER CLIPRDR_HEADER;
struct _cliprdr_server_private
{
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
BOOL UseLongFormatNames;
BOOL StreamFileClipEnabled;
BOOL FileClipNoFilePaths;
BOOL CanLockClipData;
UINT32 ClientFormatNameCount;
CLIPRDR_FORMAT_NAME* ClientFormatNames;
char* ClientTemporaryDirectory;
};
#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H */

View File

@ -21,3 +21,6 @@ if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -1,7 +1,7 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT OFF)
set(OPTION_SERVER_DEFAULT ON)
define_channel_options(NAME "drdynvc" TYPE "static"
DESCRIPTION "Dynamic Virtual Channel Extension"

View File

@ -0,0 +1,35 @@
# 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("drdynvc")
set(${MODULE_PREFIX}_SRCS
drdynvc_main.c
drdynvc_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")

View File

@ -0,0 +1,149 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Dynamic 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/print.h>
#include <winpr/stream.h>
#include "drdynvc_main.h"
static void* drdynvc_server_thread(void* arg)
{
wStream* s;
DWORD status;
DWORD nCount;
void* buffer;
HANDLE events[8];
HANDLE ChannelEvent;
DWORD BytesReturned;
DrdynvcServerContext* context;
context = (DrdynvcServerContext*) 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,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
{
if (BytesReturned)
Stream_Seek(s, BytesReturned);
}
else
{
Stream_EnsureRemainingCapacity(s, BytesReturned);
}
}
Stream_Free(s, TRUE);
return NULL;
}
static int drdynvc_server_start(DrdynvcServerContext* context)
{
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdr", 0);
if (!context->priv->ChannelHandle)
return -1;
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL);
return 0;
}
static int drdynvc_server_stop(DrdynvcServerContext* context)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
return 0;
}
DrdynvcServerContext* drdynvc_server_context_new(WTSVirtualChannelManager* vcm)
{
DrdynvcServerContext* context;
context = (DrdynvcServerContext*) malloc(sizeof(DrdynvcServerContext));
if (context)
{
ZeroMemory(context, sizeof(DrdynvcServerContext));
context->vcm = vcm;
context->Start = drdynvc_server_start;
context->Stop = drdynvc_server_stop;
context->priv = (DrdynvcServerPrivate*) malloc(sizeof(DrdynvcServerPrivate));
if (context->priv)
{
ZeroMemory(context->priv, sizeof(DrdynvcServerPrivate));
}
}
return context;
}
void drdynvc_server_context_free(DrdynvcServerContext* context)
{
if (context)
{
if (context->priv)
{
free(context->priv);
}
free(context);
}
}

View File

@ -0,0 +1,37 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Dynamic 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_DRDYNVC_MAIN_H
#define FREERDP_CHANNEL_SERVER_DRDYNVC_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <freerdp/settings.h>
#include <freerdp/server/drdynvc.h>
struct _drdynvc_server_private
{
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
};
#endif /* FREERDP_CHANNEL_SERVER_DRDYNVC_MAIN_H */

View File

@ -20,3 +20,7 @@ define_channel("rdpdr")
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -1,7 +1,7 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT OFF)
set(OPTION_SERVER_DEFAULT ON)
define_channel_options(NAME "rdpdr" TYPE "static"
DESCRIPTION "Device Redirection Virtual Channel Extension"

View File

@ -33,132 +33,132 @@
#include "rdpdr_capabilities.h"
/* Output device redirection capability set header */
static void rdpdr_write_capset_header(wStream* data_out, UINT16 capabilityType, UINT16 capabilityLength, UINT32 version)
static void rdpdr_write_capset_header(wStream* s, UINT16 capabilityType, UINT16 capabilityLength, UINT32 version)
{
Stream_Write_UINT16(data_out, capabilityType);
Stream_Write_UINT16(data_out, capabilityLength);
Stream_Write_UINT32(data_out, version);
Stream_Write_UINT16(s, capabilityType);
Stream_Write_UINT16(s, capabilityLength);
Stream_Write_UINT32(s, version);
}
/* Output device direction general capability set */
static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* data_out)
static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s)
{
rdpdr_write_capset_header(data_out, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02);
rdpdr_write_capset_header(s, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02);
Stream_Write_UINT32(data_out, 0); /* osType, ignored on receipt */
Stream_Write_UINT32(data_out, 0); /* osVersion, unused and must be set to zero */
Stream_Write_UINT16(data_out, 1); /* protocolMajorVersion, must be set to 1 */
Stream_Write_UINT16(data_out, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */
Stream_Write_UINT32(data_out, 0x0000FFFF); /* ioCode1 */
Stream_Write_UINT32(data_out, 0); /* ioCode2, must be set to zero, reserved for future use */
Stream_Write_UINT32(data_out, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
Stream_Write_UINT32(data_out, ENABLE_ASYNCIO); /* extraFlags1 */
Stream_Write_UINT32(data_out, 0); /* extraFlags2, must be set to zero, reserved for future use */
Stream_Write_UINT32(data_out, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */
Stream_Write_UINT32(s, 0); /* osType, ignored on receipt */
Stream_Write_UINT32(s, 0); /* osVersion, unused and must be set to zero */
Stream_Write_UINT16(s, 1); /* protocolMajorVersion, must be set to 1 */
Stream_Write_UINT16(s, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */
Stream_Write_UINT32(s, 0x0000FFFF); /* ioCode1 */
Stream_Write_UINT32(s, 0); /* ioCode2, must be set to zero, reserved for future use */
Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
Stream_Write_UINT32(s, ENABLE_ASYNCIO); /* extraFlags1 */
Stream_Write_UINT32(s, 0); /* extraFlags2, must be set to zero, reserved for future use */
Stream_Write_UINT32(s, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */
}
/* Process device direction general capability set */
static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 capabilityLength;
Stream_Read_UINT16(data_in, capabilityLength);
Stream_Seek(data_in, capabilityLength - 4);
Stream_Read_UINT16(s, capabilityLength);
Stream_Seek(s, capabilityLength - 4);
}
/* Output printer direction capability set */
static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* data_out)
static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* s)
{
rdpdr_write_capset_header(data_out, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01);
rdpdr_write_capset_header(s, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01);
}
/* Process printer direction capability set */
static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 capabilityLength;
Stream_Read_UINT16(data_in, capabilityLength);
Stream_Seek(data_in, capabilityLength - 4);
Stream_Read_UINT16(s, capabilityLength);
Stream_Seek(s, capabilityLength - 4);
}
/* Output port redirection capability set */
static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* data_out)
static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* s)
{
rdpdr_write_capset_header(data_out, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01);
rdpdr_write_capset_header(s, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01);
}
/* Process port redirection capability set */
static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 capabilityLength;
Stream_Read_UINT16(data_in, capabilityLength);
Stream_Seek(data_in, capabilityLength - 4);
Stream_Read_UINT16(s, capabilityLength);
Stream_Seek(s, capabilityLength - 4);
}
/* Output drive redirection capability set */
static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* data_out)
static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* s)
{
rdpdr_write_capset_header(data_out, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02);
rdpdr_write_capset_header(s, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02);
}
/* Process drive redirection capability set */
static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 capabilityLength;
Stream_Read_UINT16(data_in, capabilityLength);
Stream_Seek(data_in, capabilityLength - 4);
Stream_Read_UINT16(s, capabilityLength);
Stream_Seek(s, capabilityLength - 4);
}
/* Output smart card redirection capability set */
static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* data_out)
static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s)
{
rdpdr_write_capset_header(data_out, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01);
rdpdr_write_capset_header(s, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01);
}
/* Process smartcard redirection capability set */
static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 capabilityLength;
Stream_Read_UINT16(data_in, capabilityLength);
Stream_Seek(data_in, capabilityLength - 4);
Stream_Read_UINT16(s, capabilityLength);
Stream_Seek(s, capabilityLength - 4);
}
void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* data_in)
void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 i;
UINT16 numCapabilities;
UINT16 capabilityType;
Stream_Read_UINT16(data_in, numCapabilities);
Stream_Seek(data_in, 2); /* pad (2 bytes) */
Stream_Read_UINT16(s, numCapabilities);
Stream_Seek(s, 2); /* pad (2 bytes) */
for(i = 0; i < numCapabilities; i++)
for (i = 0; i < numCapabilities; i++)
{
Stream_Read_UINT16(data_in, capabilityType);
Stream_Read_UINT16(s, capabilityType);
switch (capabilityType)
{
case CAP_GENERAL_TYPE:
rdpdr_process_general_capset(rdpdr, data_in);
rdpdr_process_general_capset(rdpdr, s);
break;
case CAP_PRINTER_TYPE:
rdpdr_process_printer_capset(rdpdr, data_in);
rdpdr_process_printer_capset(rdpdr, s);
break;
case CAP_PORT_TYPE:
rdpdr_process_port_capset(rdpdr, data_in);
rdpdr_process_port_capset(rdpdr, s);
break;
case CAP_DRIVE_TYPE:
rdpdr_process_drive_capset(rdpdr, data_in);
rdpdr_process_drive_capset(rdpdr, s);
break;
case CAP_SMARTCARD_TYPE:
rdpdr_process_smartcard_capset(rdpdr, data_in);
rdpdr_process_smartcard_capset(rdpdr, s);
break;
default:
@ -170,21 +170,21 @@ void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* data_in)
void rdpdr_send_capability_response(rdpdrPlugin* rdpdr)
{
wStream* data_out;
wStream* s;
data_out = Stream_New(NULL, 256);
s = Stream_New(NULL, 256);
Stream_Write_UINT16(data_out, RDPDR_CTYP_CORE);
Stream_Write_UINT16(data_out, PAKID_CORE_CLIENT_CAPABILITY);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
Stream_Write_UINT16(s, PAKID_CORE_CLIENT_CAPABILITY);
Stream_Write_UINT16(data_out, 5); /* numCapabilities */
Stream_Write_UINT16(data_out, 0); /* pad */
Stream_Write_UINT16(s, 5); /* numCapabilities */
Stream_Write_UINT16(s, 0); /* pad */
rdpdr_write_general_capset(rdpdr, data_out);
rdpdr_write_printer_capset(rdpdr, data_out);
rdpdr_write_port_capset(rdpdr, data_out);
rdpdr_write_drive_capset(rdpdr, data_out);
rdpdr_write_smartcard_capset(rdpdr, data_out);
rdpdr_write_general_capset(rdpdr, s);
rdpdr_write_printer_capset(rdpdr, s);
rdpdr_write_port_capset(rdpdr, s);
rdpdr_write_drive_capset(rdpdr, s);
rdpdr_write_smartcard_capset(rdpdr, s);
svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out);
svc_plugin_send((rdpSvcPlugin*)rdpdr, s);
}

View File

@ -0,0 +1,35 @@
# 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("rdpdr")
set(${MODULE_PREFIX}_SRCS
rdpdr_main.c
rdpdr_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")

View File

@ -0,0 +1,699 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Device Redirection 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/print.h>
#include <winpr/stream.h>
#include "rdpdr_main.h"
static UINT32 g_ClientId = 0;
static int rdpdr_server_send_announce_request(RdpdrServerContext* context)
{
wStream* s;
BOOL status;
RDPDR_HEADER header;
printf("RdpdrServerSendAnnounceRequest\n");
header.Component = RDPDR_CTYP_CORE;
header.PacketId = PAKID_CORE_SERVER_ANNOUNCE;
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */
Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */
Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int rdpdr_server_receive_announce_response(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
{
UINT32 ClientId;
UINT16 VersionMajor;
UINT16 VersionMinor;
Stream_Read_UINT16(s, VersionMajor); /* VersionMajor (2 bytes) */
Stream_Read_UINT16(s, VersionMinor); /* VersionMinor (2 bytes) */
Stream_Read_UINT32(s, ClientId); /* ClientId (4 bytes) */
printf("Client Announce Response: VersionMajor: 0x%04X VersionMinor: 0x%04X ClientId: 0x%04X\n",
VersionMajor, VersionMinor, ClientId);
context->priv->ClientId = ClientId;
return 0;
}
static int rdpdr_server_receive_client_name_request(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
{
UINT32 UnicodeFlag;
UINT32 ComputerNameLen;
Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */
Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */
Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */
/**
* Caution: ComputerNameLen is given *bytes*,
* not in characters, including the NULL terminator!
*/
if (context->priv->ClientComputerName)
{
free(context->priv->ClientComputerName);
context->priv->ClientComputerName = NULL;
}
if (UnicodeFlag)
{
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
-1, &(context->priv->ClientComputerName), 0, NULL, NULL);
}
else
{
context->priv->ClientComputerName = _strdup((char*) Stream_Pointer(s));
}
Stream_Seek(s, ComputerNameLen);
printf("ClientComputerName: %s\n", context->priv->ClientComputerName);
return 0;
}
static int rdpdr_server_read_capability_set_header(wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
Stream_Read_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */
Stream_Read_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */
Stream_Read_UINT32(s, header->Version); /* Version (4 bytes) */
return 0;
}
static int rdpdr_server_write_capability_set_header(wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
Stream_Write_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */
Stream_Write_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */
Stream_Write_UINT32(s, header->Version); /* Version (4 bytes) */
return 0;
}
static int rdpdr_server_read_general_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
UINT32 ioCode1;
UINT32 extraFlags1;
UINT32 extendedPdu;
UINT16 VersionMajor;
UINT16 VersionMinor;
UINT32 SpecialTypeDeviceCap;
Stream_Seek_UINT32(s); /* osType (4 bytes), ignored on receipt */
Stream_Seek_UINT32(s); /* osVersion (4 bytes), unused and must be set to zero */
Stream_Read_UINT16(s, VersionMajor); /* protocolMajorVersion (2 bytes) */
Stream_Read_UINT16(s, VersionMinor); /* protocolMinorVersion (2 bytes) */
Stream_Read_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */
Stream_Seek_UINT32(s); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */
Stream_Read_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */
Stream_Read_UINT32(s, extraFlags1); /* extraFlags1 (4 bytes) */
Stream_Seek_UINT32(s); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */
Stream_Read_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */
context->priv->UserLoggedOnPdu = (extendedPdu & RDPDR_USER_LOGGEDON_PDU) ? TRUE : FALSE;
return 0;
}
static int rdpdr_server_write_general_capability_set(RdpdrServerContext* context, wStream* s)
{
UINT32 ioCode1;
UINT32 extendedPdu;
UINT32 extraFlags1;
UINT32 SpecialTypeDeviceCap;
RDPDR_CAPABILITY_HEADER header;
header.CapabilityType = CAP_GENERAL_TYPE;
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH + 36;
header.Version = GENERAL_CAPABILITY_VERSION_02;
ioCode1 = 0;
ioCode1 |= RDPDR_IRP_MJ_CREATE; /* always set */
ioCode1 |= RDPDR_IRP_MJ_CLEANUP; /* always set */
ioCode1 |= RDPDR_IRP_MJ_CLOSE; /* always set */
ioCode1 |= RDPDR_IRP_MJ_READ; /* always set */
ioCode1 |= RDPDR_IRP_MJ_WRITE; /* always set */
ioCode1 |= RDPDR_IRP_MJ_FLUSH_BUFFERS; /* always set */
ioCode1 |= RDPDR_IRP_MJ_SHUTDOWN; /* always set */
ioCode1 |= RDPDR_IRP_MJ_DEVICE_CONTROL; /* always set */
ioCode1 |= RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION; /* always set */
ioCode1 |= RDPDR_IRP_MJ_SET_VOLUME_INFORMATION; /* always set */
ioCode1 |= RDPDR_IRP_MJ_QUERY_INFORMATION; /* always set */
ioCode1 |= RDPDR_IRP_MJ_SET_INFORMATION; /* always set */
ioCode1 |= RDPDR_IRP_MJ_DIRECTORY_CONTROL; /* always set */
ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL; /* always set */
ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY; /* optional */
ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY; /* optional */
extendedPdu = 0;
extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU; /* always set */
extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS; /* optional */
if (context->priv->UserLoggedOnPdu)
extendedPdu |= RDPDR_USER_LOGGEDON_PDU; /* optional */
extraFlags1 = 0;
extraFlags1 |= ENABLE_ASYNCIO; /* optional */
SpecialTypeDeviceCap = 0;
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
rdpdr_server_write_capability_set_header(s, &header);
Stream_Write_UINT32(s, 0); /* osType (4 bytes), ignored on receipt */
Stream_Write_UINT32(s, 0); /* osVersion (4 bytes), unused and must be set to zero */
Stream_Write_UINT16(s, context->priv->VersionMajor); /* protocolMajorVersion (2 bytes) */
Stream_Write_UINT16(s, context->priv->VersionMinor); /* protocolMinorVersion (2 bytes) */
Stream_Write_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */
Stream_Write_UINT32(s, 0); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */
Stream_Write_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */
Stream_Write_UINT32(s, extraFlags1); /* extraFlags1 (4 bytes) */
Stream_Write_UINT32(s, 0); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */
Stream_Write_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */
return 0;
}
static int rdpdr_server_read_printer_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
return 0;
}
static int rdpdr_server_write_printer_capability_set(RdpdrServerContext* context, wStream* s)
{
RDPDR_CAPABILITY_HEADER header;
header.CapabilityType = CAP_PRINTER_TYPE;
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
header.Version = PRINT_CAPABILITY_VERSION_01;
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
rdpdr_server_write_capability_set_header(s, &header);
return 0;
}
static int rdpdr_server_read_port_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
return 0;
}
static int rdpdr_server_write_port_capability_set(RdpdrServerContext* context, wStream* s)
{
RDPDR_CAPABILITY_HEADER header;
header.CapabilityType = CAP_PORT_TYPE;
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
header.Version = PORT_CAPABILITY_VERSION_01;
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
rdpdr_server_write_capability_set_header(s, &header);
return 0;
}
static int rdpdr_server_read_drive_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
return 0;
}
static int rdpdr_server_write_drive_capability_set(RdpdrServerContext* context, wStream* s)
{
RDPDR_CAPABILITY_HEADER header;
header.CapabilityType = CAP_DRIVE_TYPE;
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
header.Version = DRIVE_CAPABILITY_VERSION_02;
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
rdpdr_server_write_capability_set_header(s, &header);
return 0;
}
static int rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
return 0;
}
static int rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* context, wStream* s)
{
RDPDR_CAPABILITY_HEADER header;
header.CapabilityType = CAP_SMARTCARD_TYPE;
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
header.Version = SMARTCARD_CAPABILITY_VERSION_01;
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
rdpdr_server_write_capability_set_header(s, &header);
return 0;
}
static int rdpdr_server_send_core_capability_request(RdpdrServerContext* context)
{
wStream* s;
BOOL status;
RDPDR_HEADER header;
UINT16 numCapabilities;
printf("RdpdrServerSendCoreCapabilityRequest\n");
header.Component = RDPDR_CTYP_CORE;
header.PacketId = PAKID_CORE_SERVER_CAPABILITY;
numCapabilities = 5;
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 512);
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
Stream_Write_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */
Stream_Write_UINT16(s, 0); /* Padding (2 bytes) */
rdpdr_server_write_general_capability_set(context, s);
rdpdr_server_write_printer_capability_set(context, s);
rdpdr_server_write_port_capability_set(context, s);
rdpdr_server_write_drive_capability_set(context, s);
rdpdr_server_write_smartcard_capability_set(context, s);
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int rdpdr_server_receive_core_capability_response(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
{
int i;
UINT16 numCapabilities;
RDPDR_CAPABILITY_HEADER capabilityHeader;
Stream_Read_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */
Stream_Seek_UINT16(s); /* Padding (2 bytes) */
for (i = 0; i < numCapabilities; i++)
{
rdpdr_server_read_capability_set_header(s, &capabilityHeader);
switch (capabilityHeader.CapabilityType)
{
case CAP_GENERAL_TYPE:
rdpdr_server_read_general_capability_set(context, s, &capabilityHeader);
break;
case CAP_PRINTER_TYPE:
rdpdr_server_read_printer_capability_set(context, s, &capabilityHeader);
break;
case CAP_PORT_TYPE:
rdpdr_server_read_port_capability_set(context, s, &capabilityHeader);
break;
case CAP_DRIVE_TYPE:
rdpdr_server_read_drive_capability_set(context, s, &capabilityHeader);
break;
case CAP_SMARTCARD_TYPE:
rdpdr_server_read_smartcard_capability_set(context, s, &capabilityHeader);
break;
default:
printf("Unknown capabilityType %d\n", capabilityHeader.CapabilityType);
Stream_Seek(s, capabilityHeader.CapabilityLength - RDPDR_CAPABILITY_HEADER_LENGTH);
break;
}
}
return 0;
}
static int rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
{
wStream* s;
BOOL status;
RDPDR_HEADER header;
printf("RdpdrServerSendClientIdConfirm\n");
header.Component = RDPDR_CTYP_CORE;
header.PacketId = PAKID_CORE_CLIENTID_CONFIRM;
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */
Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */
Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int rdpdr_server_receive_device_list_announce_request(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
{
int i;
UINT32 DeviceCount;
UINT32 DeviceType;
UINT32 DeviceId;
char PreferredDosName[9];
UINT32 DeviceDataLength;
PreferredDosName[8] = 0;
Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */
printf("%s: DeviceCount: %d\n", __FUNCTION__, DeviceCount);
for (i = 0; i < DeviceCount; i++)
{
Stream_Read_UINT32(s, DeviceType); /* DeviceType (4 bytes) */
Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */
Stream_Read(s, PreferredDosName, 8); /* PreferredDosName (8 bytes) */
Stream_Read_UINT32(s, DeviceDataLength); /* DeviceDataLength (4 bytes) */
printf("Device %d Name: %s Id: 0x%04X DataLength: %d\n",
i, PreferredDosName, DeviceId, DeviceDataLength);
switch (DeviceId)
{
case RDPDR_DTYP_FILESYSTEM:
break;
case RDPDR_DTYP_PRINT:
break;
case RDPDR_DTYP_SERIAL:
break;
case RDPDR_DTYP_PARALLEL:
break;
case RDPDR_DTYP_SMARTCARD:
break;
default:
break;
}
Stream_Seek(s, DeviceDataLength);
}
return 0;
}
static int rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
{
wStream* s;
BOOL status;
RDPDR_HEADER header;
printf("%s\n", __FUNCTION__);
header.Component = RDPDR_CTYP_CORE;
header.PacketId = PAKID_CORE_USER_LOGGEDON;
s = Stream_New(NULL, RDPDR_HEADER_LENGTH);
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
{
printf("RdpdrServerReceivePdu: Component: 0x%04X PacketId: 0x%04X\n",
header->Component, header->PacketId);
winpr_HexDump(Stream_Buffer(s), Stream_Length(s));
if (header->Component == RDPDR_CTYP_CORE)
{
switch (header->PacketId)
{
case PAKID_CORE_CLIENTID_CONFIRM:
rdpdr_server_receive_announce_response(context, s, header);
break;
case PAKID_CORE_CLIENT_NAME:
rdpdr_server_receive_client_name_request(context, s, header);
rdpdr_server_send_core_capability_request(context);
break;
case PAKID_CORE_CLIENT_CAPABILITY:
rdpdr_server_receive_core_capability_response(context, s, header);
rdpdr_server_send_client_id_confirm(context);
if (context->priv->UserLoggedOnPdu)
rdpdr_server_send_user_logged_on(context);
break;
case PAKID_CORE_DEVICELIST_ANNOUNCE:
rdpdr_server_receive_device_list_announce_request(context, s, header);
break;
case PAKID_CORE_DEVICE_REPLY:
break;
case PAKID_CORE_DEVICE_IOREQUEST:
break;
case PAKID_CORE_DEVICE_IOCOMPLETION:
break;
case PAKID_CORE_DEVICELIST_REMOVE:
break;
default:
break;
}
}
else if (header->Component == RDPDR_CTYP_PRN)
{
switch (header->PacketId)
{
case PAKID_PRN_CACHE_DATA:
break;
case PAKID_PRN_USING_XPS:
break;
default:
break;
}
}
else
{
printf("Unknown RDPDR_HEADER.Component: 0x%04X\n", header->Component);
return -1;
}
return 0;
}
static void* rdpdr_server_thread(void* arg)
{
wStream* s;
DWORD status;
DWORD nCount;
void* buffer;
int position;
HANDLE events[8];
RDPDR_HEADER header;
HANDLE ChannelEvent;
DWORD BytesReturned;
RdpdrServerContext* context;
context = (RdpdrServerContext*) 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;
rdpdr_server_send_announce_request(context);
while (1)
{
BytesReturned = 0;
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Pointer(s),
Stream_Capacity(s) - Stream_GetPosition(s), &BytesReturned))
{
if (BytesReturned)
Stream_Seek(s, BytesReturned);
}
else
{
Stream_EnsureRemainingCapacity(s, BytesReturned);
}
if (Stream_GetPosition(s) >= RDPDR_HEADER_LENGTH)
{
position = Stream_GetPosition(s);
Stream_SetPosition(s, 0);
Stream_Read_UINT16(s, header.Component); /* Component (2 bytes) */
Stream_Read_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
Stream_SetPosition(s, position);
Stream_SealLength(s);
Stream_SetPosition(s, RDPDR_HEADER_LENGTH);
rdpdr_server_receive_pdu(context, s, &header);
Stream_SetPosition(s, 0);
}
}
Stream_Free(s, TRUE);
return NULL;
}
static int rdpdr_server_start(RdpdrServerContext* context)
{
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdr", 0);
if (!context->priv->ChannelHandle)
return -1;
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpdr_server_thread, (void*) context, 0, NULL);
return 0;
}
static int rdpdr_server_stop(RdpdrServerContext* context)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
return 0;
}
RdpdrServerContext* rdpdr_server_context_new(WTSVirtualChannelManager* vcm)
{
RdpdrServerContext* context;
context = (RdpdrServerContext*) malloc(sizeof(RdpdrServerContext));
if (context)
{
ZeroMemory(context, sizeof(RdpdrServerContext));
context->vcm = vcm;
context->Start = rdpdr_server_start;
context->Stop = rdpdr_server_stop;
context->priv = (RdpdrServerPrivate*) malloc(sizeof(RdpdrServerPrivate));
if (context->priv)
{
ZeroMemory(context->priv, sizeof(RdpdrServerPrivate));
context->priv->VersionMajor = RDPDR_VERSION_MAJOR;
context->priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
context->priv->ClientId = g_ClientId++;
context->priv->UserLoggedOnPdu = TRUE;
}
}
return context;
}
void rdpdr_server_context_free(RdpdrServerContext* context)
{
if (context)
{
if (context->priv)
{
free(context->priv);
}
free(context);
}
}

View File

@ -0,0 +1,70 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Device Redirection 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_RDPDR_MAIN_H
#define FREERDP_CHANNEL_SERVER_RDPDR_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <freerdp/settings.h>
#include <freerdp/server/rdpdr.h>
struct _rdpdr_server_private
{
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
UINT32 ClientId;
UINT16 VersionMajor;
UINT16 VersionMinor;
char* ClientComputerName;
BOOL UserLoggedOnPdu;
};
#define RDPDR_HEADER_LENGTH 4
struct _RDPDR_HEADER
{
UINT16 Component;
UINT16 PacketId;
};
typedef struct _RDPDR_HEADER RDPDR_HEADER;
#define RDPDR_VERSION_MAJOR 0x0001
#define RDPDR_VERSION_MINOR_RDP50 0x0002
#define RDPDR_VERSION_MINOR_RDP51 0x0005
#define RDPDR_VERSION_MINOR_RDP52 0x000A
#define RDPDR_VERSION_MINOR_RDP6X 0x000C
#define RDPDR_CAPABILITY_HEADER_LENGTH 8
struct _RDPDR_CAPABILITY_HEADER
{
UINT16 CapabilityType;
UINT16 CapabilityLength;
UINT32 Version;
};
typedef struct _RDPDR_CAPABILITY_HEADER RDPDR_CAPABILITY_HEADER;
#endif /* FREERDP_CHANNEL_SERVER_RDPDR_MAIN_H */

View File

@ -18,7 +18,8 @@
define_channel_server("rdpsnd")
set(${MODULE_PREFIX}_SRCS
rdpsnd.c)
rdpsnd_main.c
rdpsnd_main.h)
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")

View File

@ -1,560 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Server Audio Virtual Channel
*
* Copyright 2012 Vic Lee
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/server/rdpsnd.h>
typedef struct _rdpsnd_server
{
rdpsnd_server_context context;
HANDLE thread;
HANDLE StopEvent;
void* rdpsnd_channel;
wStream* rdpsnd_pdu;
FREERDP_DSP_CONTEXT* dsp_context;
BYTE* out_buffer;
int out_buffer_size;
int out_frames;
int out_pending_frames;
UINT32 src_bytes_per_sample;
UINT32 src_bytes_per_frame;
} rdpsnd_server;
static BOOL rdpsnd_server_send_formats(rdpsnd_server* rdpsnd, wStream* s)
{
int pos;
UINT16 i;
BOOL status;
Stream_Write_UINT8(s, SNDC_FORMATS);
Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s);
Stream_Write_UINT32(s, 0); /* dwFlags */
Stream_Write_UINT32(s, 0); /* dwVolume */
Stream_Write_UINT32(s, 0); /* dwPitch */
Stream_Write_UINT16(s, 0); /* wDGramPort */
Stream_Write_UINT16(s, rdpsnd->context.num_server_formats); /* wNumberOfFormats */
Stream_Write_UINT8(s, rdpsnd->context.block_no); /* cLastBlockConfirmed */
Stream_Write_UINT16(s, 0x06); /* wVersion */
Stream_Write_UINT8(s, 0); /* bPad */
for (i = 0; i < rdpsnd->context.num_server_formats; i++)
{
Stream_Write_UINT16(s, rdpsnd->context.server_formats[i].wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */
Stream_Write_UINT16(s, rdpsnd->context.server_formats[i].nChannels); /* nChannels */
Stream_Write_UINT32(s, rdpsnd->context.server_formats[i].nSamplesPerSec); /* nSamplesPerSec */
Stream_Write_UINT32(s, rdpsnd->context.server_formats[i].nSamplesPerSec *
rdpsnd->context.server_formats[i].nChannels *
rdpsnd->context.server_formats[i].wBitsPerSample / 8); /* nAvgBytesPerSec */
Stream_Write_UINT16(s, rdpsnd->context.server_formats[i].nBlockAlign); /* nBlockAlign */
Stream_Write_UINT16(s, rdpsnd->context.server_formats[i].wBitsPerSample); /* wBitsPerSample */
Stream_Write_UINT16(s, rdpsnd->context.server_formats[i].cbSize); /* cbSize */
if (rdpsnd->context.server_formats[i].cbSize > 0)
{
Stream_Write(s, rdpsnd->context.server_formats[i].data, rdpsnd->context.server_formats[i].cbSize);
}
}
pos = Stream_GetPosition(s);
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(rdpsnd->rdpsnd_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
return status;
}
static void rdpsnd_server_recv_waveconfirm(rdpsnd_server* rdpsnd, wStream* s)
{
//unhandled for now
UINT16 timestamp = 0;
BYTE confirmBlockNum = 0;
Stream_Read_UINT16(s, timestamp);
Stream_Read_UINT8(s, confirmBlockNum);
Stream_Seek_UINT8(s); // padding
}
static void rdpsnd_server_recv_quality_mode(rdpsnd_server* rdpsnd, wStream* s)
{
//unhandled for now
UINT16 quality;
Stream_Read_UINT16(s, quality);
Stream_Seek_UINT16(s); // reserved
fprintf(stderr, "Client requested sound quality: %#0X\n", quality);
}
static BOOL rdpsnd_server_recv_formats(rdpsnd_server* rdpsnd, wStream* s)
{
int i, num_known_format = 0;
UINT32 flags, vol, pitch;
UINT16 udpPort, version;
BYTE lastblock;
Stream_Read_UINT32(s, flags); /* dwFlags */
Stream_Read_UINT32(s, vol); /* dwVolume */
Stream_Read_UINT32(s, pitch); /* dwPitch */
Stream_Read_UINT16(s, udpPort); /* wDGramPort */
Stream_Read_UINT16(s, rdpsnd->context.num_client_formats); /* wNumberOfFormats */
Stream_Read_UINT8(s, lastblock); /* cLastBlockConfirmed */
Stream_Read_UINT16(s, version); /* wVersion */
Stream_Seek_UINT8(s); /* bPad */
if (rdpsnd->context.num_client_formats > 0)
{
rdpsnd->context.client_formats = (AUDIO_FORMAT*) malloc(rdpsnd->context.num_client_formats * sizeof(AUDIO_FORMAT));
ZeroMemory(rdpsnd->context.client_formats, sizeof(AUDIO_FORMAT));
for (i = 0; i < rdpsnd->context.num_client_formats; i++)
{
Stream_Read_UINT16(s, rdpsnd->context.client_formats[i].wFormatTag);
Stream_Read_UINT16(s, rdpsnd->context.client_formats[i].nChannels);
Stream_Read_UINT32(s, rdpsnd->context.client_formats[i].nSamplesPerSec);
Stream_Read_UINT32(s, rdpsnd->context.client_formats[i].nAvgBytesPerSec);
Stream_Read_UINT16(s, rdpsnd->context.client_formats[i].nBlockAlign);
Stream_Read_UINT16(s, rdpsnd->context.client_formats[i].wBitsPerSample);
Stream_Read_UINT16(s, rdpsnd->context.client_formats[i].cbSize);
if (rdpsnd->context.client_formats[i].cbSize > 0)
{
Stream_Seek(s, rdpsnd->context.client_formats[i].cbSize);
}
if (rdpsnd->context.client_formats[i].wFormatTag != 0)
{
//lets call this a known format
//TODO: actually look through our own list of known formats
num_known_format++;
}
}
}
if (num_known_format == 0)
{
fprintf(stderr, "Client doesnt support any known formats!\n");
return FALSE;
}
return TRUE;
}
static void* rdpsnd_server_thread_func(void* arg)
{
void* fd;
wStream* s;
void* buffer;
DWORD status;
BYTE msgType;
UINT16 BodySize;
HANDLE events[2];
UINT32 bytes_returned = 0;
rdpsnd_server* rdpsnd = (rdpsnd_server*) arg;
events[0] = rdpsnd->StopEvent;
if (WTSVirtualChannelQuery(rdpsnd->rdpsnd_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == TRUE)
{
fd = *((void**) buffer);
WTSFreeMemory(buffer);
events[1] = CreateWaitObjectEvent(NULL, TRUE, FALSE, fd);
}
s = Stream_New(NULL, 4096);
rdpsnd_server_send_formats(rdpsnd, s);
while (1)
{
status = WaitForMultipleObjects(2, events, FALSE, INFINITE);
if (WaitForSingleObject(rdpsnd->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
Stream_SetPosition(s, 0);
if (WTSVirtualChannelRead(rdpsnd->rdpsnd_channel, 0, Stream_Buffer(s),
Stream_Capacity(s), &bytes_returned) == FALSE)
{
if (bytes_returned == 0)
break;
Stream_EnsureRemainingCapacity(s, (int) bytes_returned);
if (WTSVirtualChannelRead(rdpsnd->rdpsnd_channel, 0, Stream_Buffer(s),
Stream_Capacity(s), &bytes_returned) == FALSE)
break;
}
Stream_Read_UINT8(s, msgType);
Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, BodySize);
switch (msgType)
{
case SNDC_WAVECONFIRM:
rdpsnd_server_recv_waveconfirm(rdpsnd, s);
break;
case SNDC_QUALITYMODE:
rdpsnd_server_recv_quality_mode(rdpsnd, s);
break;
case SNDC_FORMATS:
if (rdpsnd_server_recv_formats(rdpsnd, s))
{
IFCALL(rdpsnd->context.Activated, &rdpsnd->context);
}
break;
default:
fprintf(stderr, "UNKOWN MESSAGE TYPE!! (%#0X)\n\n", msgType);
break;
}
}
Stream_Free(s, TRUE);
return NULL;
}
static BOOL rdpsnd_server_initialize(rdpsnd_server_context* context)
{
rdpsnd_server* rdpsnd = (rdpsnd_server*) context;
rdpsnd->rdpsnd_channel = WTSVirtualChannelOpenEx(context->vcm, "rdpsnd", 0);
if (rdpsnd->rdpsnd_channel != NULL)
{
rdpsnd->rdpsnd_pdu = Stream_New(NULL, 4096);
rdpsnd->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpsnd->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_server_thread_func, (void*) rdpsnd, 0, NULL);
return TRUE;
}
else
{
return FALSE;
}
}
static void rdpsnd_server_select_format(rdpsnd_server_context* context, int client_format_index)
{
int bs;
int out_buffer_size;
AUDIO_FORMAT *format;
rdpsnd_server* rdpsnd = (rdpsnd_server*) context;
if (client_format_index < 0 || client_format_index >= context->num_client_formats)
{
fprintf(stderr, "rdpsnd_server_select_format: index %d is not correct.\n", client_format_index);
return;
}
rdpsnd->src_bytes_per_sample = context->src_format.wBitsPerSample / 8;
rdpsnd->src_bytes_per_frame = rdpsnd->src_bytes_per_sample * context->src_format.nChannels;
context->selected_client_format = client_format_index;
format = &context->client_formats[client_format_index];
if (format->nSamplesPerSec == 0)
{
fprintf(stderr, "Invalid Client Sound Format!!\n\n");
return;
}
if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
{
bs = (format->nBlockAlign - 4 * format->nChannels) * 4;
rdpsnd->out_frames = (format->nBlockAlign * 4 * format->nChannels * 2 / bs + 1) * bs / (format->nChannels * 2);
}
else if (format->wFormatTag == WAVE_FORMAT_ADPCM)
{
bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2;
rdpsnd->out_frames = bs * 4;
}
else
{
rdpsnd->out_frames = 0x4000 / rdpsnd->src_bytes_per_frame;
}
if (format->nSamplesPerSec != context->src_format.nSamplesPerSec)
{
rdpsnd->out_frames = (rdpsnd->out_frames * context->src_format.nSamplesPerSec + format->nSamplesPerSec - 100) / format->nSamplesPerSec;
}
rdpsnd->out_pending_frames = 0;
out_buffer_size = rdpsnd->out_frames * rdpsnd->src_bytes_per_frame;
if (rdpsnd->out_buffer_size < out_buffer_size)
{
rdpsnd->out_buffer = (BYTE*) realloc(rdpsnd->out_buffer, out_buffer_size);
rdpsnd->out_buffer_size = out_buffer_size;
}
freerdp_dsp_context_reset_adpcm(rdpsnd->dsp_context);
}
static BOOL rdpsnd_server_send_audio_pdu(rdpsnd_server* rdpsnd)
{
int size;
BYTE* src;
int frames;
int fill_size;
BOOL status;
AUDIO_FORMAT* format;
int tbytes_per_frame;
wStream* s = rdpsnd->rdpsnd_pdu;
format = &rdpsnd->context.client_formats[rdpsnd->context.selected_client_format];
tbytes_per_frame = format->nChannels * rdpsnd->src_bytes_per_sample;
if ((format->nSamplesPerSec == rdpsnd->context.src_format.nSamplesPerSec) &&
(format->nChannels == rdpsnd->context.src_format.nChannels))
{
src = rdpsnd->out_buffer;
frames = rdpsnd->out_pending_frames;
}
else
{
rdpsnd->dsp_context->resample(rdpsnd->dsp_context, rdpsnd->out_buffer, rdpsnd->src_bytes_per_sample,
rdpsnd->context.src_format.nChannels, rdpsnd->context.src_format.nSamplesPerSec, rdpsnd->out_pending_frames,
format->nChannels, format->nSamplesPerSec);
frames = rdpsnd->dsp_context->resampled_frames;
src = rdpsnd->dsp_context->resampled_buffer;
}
size = frames * tbytes_per_frame;
if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
{
rdpsnd->dsp_context->encode_ima_adpcm(rdpsnd->dsp_context,
src, size, format->nChannels, format->nBlockAlign);
src = rdpsnd->dsp_context->adpcm_buffer;
size = rdpsnd->dsp_context->adpcm_size;
}
else if (format->wFormatTag == WAVE_FORMAT_ADPCM)
{
rdpsnd->dsp_context->encode_ms_adpcm(rdpsnd->dsp_context,
src, size, format->nChannels, format->nBlockAlign);
src = rdpsnd->dsp_context->adpcm_buffer;
size = rdpsnd->dsp_context->adpcm_size;
}
rdpsnd->context.block_no = (rdpsnd->context.block_no + 1) % 256;
/* Fill to nBlockAlign for the last audio packet */
fill_size = 0;
if ((format->wFormatTag == WAVE_FORMAT_DVI_ADPCM || format->wFormatTag == WAVE_FORMAT_ADPCM) &&
(rdpsnd->out_pending_frames < rdpsnd->out_frames) && ((size % format->nBlockAlign) != 0))
{
fill_size = format->nBlockAlign - (size % format->nBlockAlign);
}
/* WaveInfo PDU */
Stream_SetPosition(s, 0);
Stream_Write_UINT8(s, SNDC_WAVE); /* msgType */
Stream_Write_UINT8(s, 0); /* bPad */
Stream_Write_UINT16(s, size + fill_size + 8); /* BodySize */
Stream_Write_UINT16(s, 0); /* wTimeStamp */
Stream_Write_UINT16(s, rdpsnd->context.selected_client_format); /* wFormatNo */
Stream_Write_UINT8(s, rdpsnd->context.block_no); /* cBlockNo */
Stream_Seek(s, 3); /* bPad */
Stream_Write(s, src, 4);
WTSVirtualChannelWrite(rdpsnd->rdpsnd_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
/* Wave PDU */
Stream_EnsureRemainingCapacity(s, size + fill_size);
Stream_Write_UINT32(s, 0); /* bPad */
Stream_Write(s, src + 4, size - 4);
if (fill_size > 0)
Stream_Zero(s, fill_size);
status = WTSVirtualChannelWrite(rdpsnd->rdpsnd_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
rdpsnd->out_pending_frames = 0;
return status;
}
static BOOL rdpsnd_server_send_samples(rdpsnd_server_context* context, const void* buf, int nframes)
{
int cframes;
int cframesize;
rdpsnd_server* rdpsnd = (rdpsnd_server*) context;
if (rdpsnd->context.selected_client_format < 0)
return FALSE;
while (nframes > 0)
{
cframes = MIN(nframes, rdpsnd->out_frames - rdpsnd->out_pending_frames);
cframesize = cframes * rdpsnd->src_bytes_per_frame;
CopyMemory(rdpsnd->out_buffer + (rdpsnd->out_pending_frames * rdpsnd->src_bytes_per_frame), buf, cframesize);
buf = (BYTE*) buf + cframesize;
nframes -= cframes;
rdpsnd->out_pending_frames += cframes;
if (rdpsnd->out_pending_frames >= rdpsnd->out_frames)
{
if (!rdpsnd_server_send_audio_pdu(rdpsnd))
return FALSE;
}
}
return TRUE;
}
static BOOL rdpsnd_server_set_volume(rdpsnd_server_context* context, int left, int right)
{
int pos;
BOOL status;
rdpsnd_server* rdpsnd = (rdpsnd_server*) context;
wStream* s = rdpsnd->rdpsnd_pdu;
Stream_Write_UINT8(s, SNDC_SETVOLUME);
Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s);
Stream_Write_UINT16(s, left);
Stream_Write_UINT16(s, right);
pos = Stream_GetPosition(s);
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(rdpsnd->rdpsnd_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
return status;
}
static BOOL rdpsnd_server_close(rdpsnd_server_context* context)
{
int pos;
BOOL status;
rdpsnd_server* rdpsnd = (rdpsnd_server*) context;
wStream* s = rdpsnd->rdpsnd_pdu;
if (rdpsnd->context.selected_client_format < 0)
return FALSE;
if (rdpsnd->out_pending_frames > 0)
{
if (!rdpsnd_server_send_audio_pdu(rdpsnd))
return FALSE;
}
rdpsnd->context.selected_client_format = -1;
Stream_Write_UINT8(s, SNDC_CLOSE);
Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s);
pos = Stream_GetPosition(s);
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(rdpsnd->rdpsnd_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
return status;
}
rdpsnd_server_context* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm)
{
rdpsnd_server* rdpsnd;
rdpsnd = (rdpsnd_server*) malloc(sizeof(rdpsnd_server));
ZeroMemory(rdpsnd, sizeof(rdpsnd_server));
rdpsnd->context.vcm = vcm;
rdpsnd->context.selected_client_format = -1;
rdpsnd->context.Initialize = rdpsnd_server_initialize;
rdpsnd->context.SelectFormat = rdpsnd_server_select_format;
rdpsnd->context.SendSamples = rdpsnd_server_send_samples;
rdpsnd->context.SetVolume = rdpsnd_server_set_volume;
rdpsnd->context.Close = rdpsnd_server_close;
rdpsnd->dsp_context = freerdp_dsp_context_new();
return (rdpsnd_server_context*) rdpsnd;
}
void rdpsnd_server_context_free(rdpsnd_server_context* context)
{
rdpsnd_server* rdpsnd = (rdpsnd_server*) context;
SetEvent(rdpsnd->StopEvent);
WaitForSingleObject(rdpsnd->thread, INFINITE);
if (rdpsnd->rdpsnd_channel)
WTSVirtualChannelClose(rdpsnd->rdpsnd_channel);
if (rdpsnd->rdpsnd_pdu)
Stream_Free(rdpsnd->rdpsnd_pdu, TRUE);
if (rdpsnd->out_buffer)
free(rdpsnd->out_buffer);
if (rdpsnd->dsp_context)
freerdp_dsp_context_free(rdpsnd->dsp_context);
if (rdpsnd->context.client_formats)
free(rdpsnd->context.client_formats);
free(rdpsnd);
}

View File

@ -0,0 +1,572 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Server Audio Virtual Channel
*
* Copyright 2012 Vic Lee
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include "rdpsnd_main.h"
static BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
{
int pos;
UINT16 i;
BOOL status;
Stream_Write_UINT8(s, SNDC_FORMATS);
Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s);
Stream_Write_UINT32(s, 0); /* dwFlags */
Stream_Write_UINT32(s, 0); /* dwVolume */
Stream_Write_UINT32(s, 0); /* dwPitch */
Stream_Write_UINT16(s, 0); /* wDGramPort */
Stream_Write_UINT16(s, context->num_server_formats); /* wNumberOfFormats */
Stream_Write_UINT8(s, context->block_no); /* cLastBlockConfirmed */
Stream_Write_UINT16(s, 0x06); /* wVersion */
Stream_Write_UINT8(s, 0); /* bPad */
for (i = 0; i < context->num_server_formats; i++)
{
Stream_Write_UINT16(s, context->server_formats[i].wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */
Stream_Write_UINT16(s, context->server_formats[i].nChannels); /* nChannels */
Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec); /* nSamplesPerSec */
Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec *
context->server_formats[i].nChannels *
context->server_formats[i].wBitsPerSample / 8); /* nAvgBytesPerSec */
Stream_Write_UINT16(s, context->server_formats[i].nBlockAlign); /* nBlockAlign */
Stream_Write_UINT16(s, context->server_formats[i].wBitsPerSample); /* wBitsPerSample */
Stream_Write_UINT16(s, context->server_formats[i].cbSize); /* cbSize */
if (context->server_formats[i].cbSize > 0)
{
Stream_Write(s, context->server_formats[i].data, context->server_formats[i].cbSize);
}
}
pos = Stream_GetPosition(s);
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
return status;
}
static void rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream* s)
{
UINT16 timestamp = 0;
BYTE confirmBlockNum = 0;
Stream_Read_UINT16(s, timestamp);
Stream_Read_UINT8(s, confirmBlockNum);
Stream_Seek_UINT8(s);
}
static void rdpsnd_server_recv_quality_mode(RdpsndServerContext* context, wStream* s)
{
UINT16 quality;
Stream_Read_UINT16(s, quality);
Stream_Seek_UINT16(s); // reserved
fprintf(stderr, "Client requested sound quality: %#0X\n", quality);
}
static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
{
int i, num_known_format = 0;
UINT32 flags, vol, pitch;
UINT16 udpPort, version;
BYTE lastblock;
Stream_Read_UINT32(s, flags); /* dwFlags */
Stream_Read_UINT32(s, vol); /* dwVolume */
Stream_Read_UINT32(s, pitch); /* dwPitch */
Stream_Read_UINT16(s, udpPort); /* wDGramPort */
Stream_Read_UINT16(s, context->num_client_formats); /* wNumberOfFormats */
Stream_Read_UINT8(s, lastblock); /* cLastBlockConfirmed */
Stream_Read_UINT16(s, version); /* wVersion */
Stream_Seek_UINT8(s); /* bPad */
if (context->num_client_formats > 0)
{
context->client_formats = (AUDIO_FORMAT*) malloc(context->num_client_formats * sizeof(AUDIO_FORMAT));
ZeroMemory(context->client_formats, sizeof(AUDIO_FORMAT));
for (i = 0; i < context->num_client_formats; i++)
{
Stream_Read_UINT16(s, context->client_formats[i].wFormatTag);
Stream_Read_UINT16(s, context->client_formats[i].nChannels);
Stream_Read_UINT32(s, context->client_formats[i].nSamplesPerSec);
Stream_Read_UINT32(s, context->client_formats[i].nAvgBytesPerSec);
Stream_Read_UINT16(s, context->client_formats[i].nBlockAlign);
Stream_Read_UINT16(s, context->client_formats[i].wBitsPerSample);
Stream_Read_UINT16(s, context->client_formats[i].cbSize);
if (context->client_formats[i].cbSize > 0)
{
Stream_Seek(s, context->client_formats[i].cbSize);
}
if (context->client_formats[i].wFormatTag != 0)
{
//lets call this a known format
//TODO: actually look through our own list of known formats
num_known_format++;
}
}
}
if (num_known_format == 0)
{
fprintf(stderr, "Client doesn't support any known formats!\n");
return FALSE;
}
return TRUE;
}
static void* rdpsnd_server_thread(void* arg)
{
wStream* s;
DWORD status;
DWORD nCount;
void* buffer;
BYTE msgType;
UINT16 BodySize;
HANDLE events[8];
HANDLE ChannelEvent;
DWORD BytesReturned;
RdpsndServerContext* context;
context = (RdpsndServerContext*) 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;
s = Stream_New(NULL, 4096);
rdpsnd_server_send_formats(context, s);
while (1)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
Stream_SetPosition(s, 0);
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) 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,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE)
{
break;
}
}
Stream_Read_UINT8(s, msgType);
Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, BodySize);
switch (msgType)
{
case SNDC_WAVECONFIRM:
rdpsnd_server_recv_waveconfirm(context, s);
break;
case SNDC_QUALITYMODE:
rdpsnd_server_recv_quality_mode(context, s);
break;
case SNDC_FORMATS:
if (rdpsnd_server_recv_formats(context, s))
{
IFCALL(context->Activated, context);
}
break;
default:
fprintf(stderr, "UNKOWN MESSAGE TYPE!! (%#0X)\n\n", msgType);
break;
}
}
Stream_Free(s, TRUE);
return NULL;
}
static BOOL rdpsnd_server_initialize(RdpsndServerContext* context)
{
context->Start(context);
return TRUE;
}
static void rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index)
{
int bs;
int out_buffer_size;
AUDIO_FORMAT *format;
if (client_format_index < 0 || client_format_index >= context->num_client_formats)
{
fprintf(stderr, "rdpsnd_server_select_format: index %d is not correct.\n", client_format_index);
return;
}
context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8;
context->priv->src_bytes_per_frame = context->priv->src_bytes_per_sample * context->src_format.nChannels;
context->selected_client_format = client_format_index;
format = &context->client_formats[client_format_index];
if (format->nSamplesPerSec == 0)
{
fprintf(stderr, "Invalid Client Sound Format!!\n\n");
return;
}
if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
{
bs = (format->nBlockAlign - 4 * format->nChannels) * 4;
context->priv->out_frames = (format->nBlockAlign * 4 * format->nChannels * 2 / bs + 1) * bs / (format->nChannels * 2);
}
else if (format->wFormatTag == WAVE_FORMAT_ADPCM)
{
bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2;
context->priv->out_frames = bs * 4;
}
else
{
context->priv->out_frames = 0x4000 / context->priv->src_bytes_per_frame;
}
if (format->nSamplesPerSec != context->src_format.nSamplesPerSec)
{
context->priv->out_frames = (context->priv->out_frames * context->src_format.nSamplesPerSec + format->nSamplesPerSec - 100) / format->nSamplesPerSec;
}
context->priv->out_pending_frames = 0;
out_buffer_size = context->priv->out_frames * context->priv->src_bytes_per_frame;
if (context->priv->out_buffer_size < out_buffer_size)
{
context->priv->out_buffer = (BYTE*) realloc(context->priv->out_buffer, out_buffer_size);
context->priv->out_buffer_size = out_buffer_size;
}
freerdp_dsp_context_reset_adpcm(context->priv->dsp_context);
}
static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context)
{
int size;
BYTE* src;
int frames;
int fill_size;
BOOL status;
AUDIO_FORMAT* format;
int tbytes_per_frame;
wStream* s = context->priv->rdpsnd_pdu;
format = &context->client_formats[context->selected_client_format];
tbytes_per_frame = format->nChannels * context->priv->src_bytes_per_sample;
if ((format->nSamplesPerSec == context->src_format.nSamplesPerSec) &&
(format->nChannels == context->src_format.nChannels))
{
src = context->priv->out_buffer;
frames = context->priv->out_pending_frames;
}
else
{
context->priv->dsp_context->resample(context->priv->dsp_context, context->priv->out_buffer,
context->priv->src_bytes_per_sample, context->src_format.nChannels,
context->src_format.nSamplesPerSec, context->priv->out_pending_frames,
format->nChannels, format->nSamplesPerSec);
frames = context->priv->dsp_context->resampled_frames;
src = context->priv->dsp_context->resampled_buffer;
}
size = frames * tbytes_per_frame;
if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
{
context->priv->dsp_context->encode_ima_adpcm(context->priv->dsp_context,
src, size, format->nChannels, format->nBlockAlign);
src = context->priv->dsp_context->adpcm_buffer;
size = context->priv->dsp_context->adpcm_size;
}
else if (format->wFormatTag == WAVE_FORMAT_ADPCM)
{
context->priv->dsp_context->encode_ms_adpcm(context->priv->dsp_context,
src, size, format->nChannels, format->nBlockAlign);
src = context->priv->dsp_context->adpcm_buffer;
size = context->priv->dsp_context->adpcm_size;
}
context->block_no = (context->block_no + 1) % 256;
/* Fill to nBlockAlign for the last audio packet */
fill_size = 0;
if ((format->wFormatTag == WAVE_FORMAT_DVI_ADPCM || format->wFormatTag == WAVE_FORMAT_ADPCM) &&
(context->priv->out_pending_frames < context->priv->out_frames) && ((size % format->nBlockAlign) != 0))
{
fill_size = format->nBlockAlign - (size % format->nBlockAlign);
}
/* WaveInfo PDU */
Stream_SetPosition(s, 0);
Stream_Write_UINT8(s, SNDC_WAVE); /* msgType */
Stream_Write_UINT8(s, 0); /* bPad */
Stream_Write_UINT16(s, size + fill_size + 8); /* BodySize */
Stream_Write_UINT16(s, 0); /* wTimeStamp */
Stream_Write_UINT16(s, context->selected_client_format); /* wFormatNo */
Stream_Write_UINT8(s, context->block_no); /* cBlockNo */
Stream_Seek(s, 3); /* bPad */
Stream_Write(s, src, 4);
WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
/* Wave PDU */
Stream_EnsureRemainingCapacity(s, size + fill_size);
Stream_Write_UINT32(s, 0); /* bPad */
Stream_Write(s, src + 4, size - 4);
if (fill_size > 0)
Stream_Zero(s, fill_size);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
context->priv->out_pending_frames = 0;
return status;
}
static BOOL rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes)
{
int cframes;
int cframesize;
if (context->selected_client_format < 0)
return FALSE;
while (nframes > 0)
{
cframes = MIN(nframes, context->priv->out_frames - context->priv->out_pending_frames);
cframesize = cframes * context->priv->src_bytes_per_frame;
CopyMemory(context->priv->out_buffer +
(context->priv->out_pending_frames * context->priv->src_bytes_per_frame), buf, cframesize);
buf = (BYTE*) buf + cframesize;
nframes -= cframes;
context->priv->out_pending_frames += cframes;
if (context->priv->out_pending_frames >= context->priv->out_frames)
{
if (!rdpsnd_server_send_audio_pdu(context))
return FALSE;
}
}
return TRUE;
}
static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int right)
{
int pos;
BOOL status;
wStream* s = context->priv->rdpsnd_pdu;
Stream_Write_UINT8(s, SNDC_SETVOLUME);
Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s);
Stream_Write_UINT16(s, left);
Stream_Write_UINT16(s, right);
pos = Stream_GetPosition(s);
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
return status;
}
static BOOL rdpsnd_server_close(RdpsndServerContext* context)
{
int pos;
BOOL status;
wStream* s = context->priv->rdpsnd_pdu;
if (context->selected_client_format < 0)
return FALSE;
if (context->priv->out_pending_frames > 0)
{
if (!rdpsnd_server_send_audio_pdu(context))
return FALSE;
}
context->selected_client_format = -1;
Stream_Write_UINT8(s, SNDC_CLOSE);
Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s);
pos = Stream_GetPosition(s);
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
return status;
}
static int rdpsnd_server_start(RdpsndServerContext* context)
{
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpsnd", 0);
if (!context->priv->ChannelHandle)
return -1;
context->priv->rdpsnd_pdu = Stream_New(NULL, 4096);
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL);
return 0;
}
static int rdpsnd_server_stop(RdpsndServerContext* context)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
return 0;
}
RdpsndServerContext* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm)
{
RdpsndServerContext* context;
context = (RdpsndServerContext*) malloc(sizeof(RdpsndServerContext));
if (context)
{
ZeroMemory(context, sizeof(RdpsndServerContext));
context->vcm = vcm;
context->Start = rdpsnd_server_start;
context->Stop = rdpsnd_server_stop;
context->selected_client_format = -1;
context->Initialize = rdpsnd_server_initialize;
context->SelectFormat = rdpsnd_server_select_format;
context->SendSamples = rdpsnd_server_send_samples;
context->SetVolume = rdpsnd_server_set_volume;
context->Close = rdpsnd_server_close;
context->priv = (RdpsndServerPrivate*) malloc(sizeof(RdpsndServerPrivate));
if (context->priv)
{
ZeroMemory(context->priv, sizeof(RdpsndServerPrivate));
context->priv->dsp_context = freerdp_dsp_context_new();
}
}
return context;
}
void rdpsnd_server_context_free(RdpsndServerContext* context)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
if (context->priv->ChannelHandle)
WTSVirtualChannelClose(context->priv->ChannelHandle);
if (context->priv->rdpsnd_pdu)
Stream_Free(context->priv->rdpsnd_pdu, TRUE);
if (context->priv->out_buffer)
free(context->priv->out_buffer);
if (context->priv->dsp_context)
freerdp_dsp_context_free(context->priv->dsp_context);
if (context->client_formats)
free(context->client_formats);
free(context);
}

View File

@ -0,0 +1,48 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Server Audio Virtual Channel
*
* Copyright 2012 Vic Lee
* 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_RDPSND_MAIN_H
#define FREERDP_CHANNEL_SERVER_RDPSND_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/server/rdpsnd.h>
struct _rdpsnd_server_private
{
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
wStream* rdpsnd_pdu;
BYTE* out_buffer;
int out_buffer_size;
int out_frames;
int out_pending_frames;
UINT32 src_bytes_per_sample;
UINT32 src_bytes_per_frame;
FREERDP_DSP_CONTEXT* dsp_context;
};
#endif /* FREERDP_CHANNEL_SERVER_RDPSND_MAIN_H */

View File

@ -42,6 +42,9 @@
#include <freerdp/server/audin.h>
#include <freerdp/server/rdpsnd.h>
#include <freerdp/server/cliprdr.h>
#include <freerdp/server/rdpdr.h>
#include <freerdp/server/drdynvc.h>
void freerdp_channels_dummy()
{
@ -50,6 +53,15 @@ void freerdp_channels_dummy()
rdpsnd_server_context_new(NULL);
rdpsnd_server_context_free(NULL);
cliprdr_server_context_new(NULL);
cliprdr_server_context_free(NULL);
rdpdr_server_context_new(NULL);
rdpdr_server_context_free(NULL);
drdynvc_server_context_new(NULL);
drdynvc_server_context_free(NULL);
}
/**
@ -420,7 +432,7 @@ WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client)
vcm = (WTSVirtualChannelManager*) malloc(sizeof(WTSVirtualChannelManager));
if (vcm != NULL)
if (vcm)
{
ZeroMemory(vcm, sizeof(WTSVirtualChannelManager));
@ -470,8 +482,7 @@ void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm)
}
}
void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm,
void** fds, int* fds_count)
void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, void** fds, int* fds_count)
{
void* fd;
@ -507,13 +518,13 @@ BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm)
/* Initialize drdynvc channel once and only once. */
vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED;
channel = WTSVirtualChannelOpenEx(vcm, "drdynvc", 0);
channel = WTSVirtualChannelManagerOpenEx(vcm, "drdynvc", 0);
if (channel)
{
vcm->drdynvc_channel = channel;
dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */
WTSVirtualChannelWrite(channel, (BYTE*) &dynvc_caps, sizeof(dynvc_caps), NULL);
WTSVirtualChannelWrite(channel, (PCHAR) &dynvc_caps, sizeof(dynvc_caps), NULL);
}
}
@ -539,10 +550,12 @@ BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm)
return result;
}
void* WTSVirtualChannelOpenEx(
/* __in */ WTSVirtualChannelManager* vcm,
/* __in */ const char* pVirtualName,
/* __in */ UINT32 flags)
HANDLE WTSVirtualChannelManagerGetEventHandle(WTSVirtualChannelManager* vcm)
{
return vcm->send_event;
}
HANDLE WTSVirtualChannelManagerOpenEx(WTSVirtualChannelManager* vcm, LPSTR pVirtualName, DWORD flags)
{
int i;
int len;
@ -592,7 +605,7 @@ void* WTSVirtualChannelOpenEx(
s = Stream_New(NULL, 64);
wts_write_drdynvc_create_request(s, channel->channel_id, pVirtualName);
WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_Free(s, TRUE);
DEBUG_DVC("ChannelId %d.%s (total %d)", channel->channel_id, pVirtualName, list_size(vcm->dvc_channel_list));
@ -646,11 +659,7 @@ void* WTSVirtualChannelOpenEx(
return channel;
}
BOOL WTSVirtualChannelQuery(
/* __in */ void* hChannelHandle,
/* __in */ WTS_VIRTUAL_CLASS WtsVirtualClass,
/* __out */ void** ppBuffer,
/* __out */ UINT32* pBytesReturned)
BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned)
{
void* pfd;
BOOL bval;
@ -659,6 +668,7 @@ BOOL WTSVirtualChannelQuery(
BOOL result = FALSE;
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
ZeroMemory(fds, sizeof(fds));
switch (WtsVirtualClass)
{
case WTSVirtualFileHandle:
@ -677,6 +687,13 @@ BOOL WTSVirtualChannelQuery(
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)
{
@ -715,25 +732,19 @@ BOOL WTSVirtualChannelQuery(
return result;
}
void WTSFreeMemory(
/* __in */ void* pMemory)
VOID WTSFreeMemory(PVOID pMemory)
{
free(pMemory);
}
BOOL WTSVirtualChannelRead(
/* __in */ void* hChannelHandle,
/* __in */ UINT32 TimeOut,
/* __out */ BYTE* Buffer,
/* __in */ UINT32 BufferSize,
/* __out */ UINT32* pBytesRead)
BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead)
{
wts_data_item* item;
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
item = (wts_data_item*) list_peek(channel->receive_queue);
if (item == NULL)
if (!item)
{
ResetEvent(channel->receive_event);
*pBytesRead = 0;
@ -755,16 +766,12 @@ BOOL WTSVirtualChannelRead(
ReleaseMutex(channel->mutex);
CopyMemory(Buffer, item->buffer, item->length);
wts_data_item_free(item) ;
wts_data_item_free(item);
return TRUE;
}
BOOL WTSVirtualChannelWrite(
/* __in */ void* hChannelHandle,
/* __in */ BYTE* Buffer,
/* __in */ UINT32 Length,
/* __out */ UINT32* pBytesWritten)
BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten)
{
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
wts_data_item* item;
@ -774,7 +781,7 @@ BOOL WTSVirtualChannelWrite(
int first;
UINT32 written;
if (channel == NULL)
if (!channel)
return FALSE;
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
@ -841,8 +848,7 @@ BOOL WTSVirtualChannelWrite(
return TRUE;
}
BOOL WTSVirtualChannelClose(
/* __in */ void* hChannelHandle)
BOOL WTSVirtualChannelClose(HANDLE hChannelHandle)
{
wStream* s;
wts_data_item* item;
@ -868,7 +874,7 @@ BOOL WTSVirtualChannelClose(
{
s = Stream_New(NULL, 8);
wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channel_id);
WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_Free(s, TRUE);
}
}

View File

@ -371,7 +371,7 @@ BOOL wf_post_connect(freerdp* instance)
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)

View File

@ -92,8 +92,6 @@ if(WITH_MANPAGES)
MODULE freerdp
MODULES freerdp-core freerdp-utils)
message(WARNING "GAD_LIBS: ${GAD_LIBS}")
target_link_libraries(generate_argument_docbook ${GAD_LIBS})
add_custom_command(OUTPUT xfreerdp.1

View File

@ -908,7 +908,7 @@ BOOL xf_post_connect(freerdp* instance)
if (instance->settings->RemoteFxCodec)
{
rfx_context = (void*) rfx_context_new();
rfx_context = (void*) rfx_context_new(FALSE);
xfc->rfx_context = rfx_context;
}

View File

@ -32,6 +32,7 @@
#cmakedefine HAVE_EVENTFD_H
#cmakedefine HAVE_TIMERFD_H
#cmakedefine HAVE_TM_GMTOFF
#cmakedefine HAVE_AIO_H
/* Options */

View File

@ -21,6 +21,7 @@
#ifndef FREERDP_CHANNEL_RDPDR_H
#define FREERDP_CHANNEL_RDPDR_H
#include <winpr/nt.h>
#include <winpr/crt.h>
#include <winpr/file.h>
#include <winpr/synch.h>
@ -113,43 +114,14 @@ enum FILE_CREATE_DISPOSITION
};
/* DR_CREATE_REQ.CreateOptions [MS-SMB2] */
enum FILE_CREATE_OPTION
{
FILE_DIRECTORY_FILE = 0x00000001,
FILE_NON_DIRECTORY_FILE = 0x00000040,
FILE_COMPLETE_IF_OPLOCKED = 0x00000100,
FILE_DELETE_ON_CLOSE = 0x00001000,
FILE_OPEN_REPARSE_POINT = 0x00200000,
FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000
};
/* DR_CREATE_REQ.DesiredAccess [MS-SMB2] */
#ifndef _WIN32
#if 0
#define FILE_READ_DATA 0x00000001
#define FILE_WRITE_DATA 0x00000002
#define FILE_APPEND_DATA 0x00000004
#define FILE_READ_EA 0x00000008
#define FILE_WRITE_EA 0x00000010
#define FILE_EXECUTE 0x00000020
#define FILE_READ_ATTRIBUTES 0x00000080
#define FILE_WRITE_ATTRIBUTES 0x00000100
#endif
#include <winpr/io.h>
#endif
/* DR_CREATE_RSP.Information */
/* DR_DRIVE_CREATE_RSP.DeviceCreateResponse */
enum FILE_RESPONSE
{
FILE_SUPERSEDED = 0x00000000,
FILE_OPENED = 0x00000001,
FILE_OVERWRITTEN = 0x00000003
};
#define FILE_OPENED 0x00000001
#define FILE_OVERWRITTEN 0x00000003
/* DR_CORE_CLIENT_ANNOUNCE_RSP.VersionMinor */
enum RDPDR_MINOR_RDP_VERSION
@ -211,73 +183,6 @@ enum RDP_LOWIO_OP
RDP_LOWIO_OP_UNLOCK_MULTIPLE = 0x00000005
};
/* NTSTATUS values */
/* http://msdn.microsoft.com/en-us/library/cc704588.aspx */
enum NTSTATUS
{
STATUS_SUCCESS = 0x00000000,
#ifndef _WIN32
STATUS_TIMEOUT = 0x00000102,
STATUS_PENDING = 0x00000103,
#endif
STATUS_REPARSE = 0x00000104,
STATUS_MORE_ENTRIES = 0x00000105,
STATUS_NOT_ALL_ASSIGNED = 0x00000106,
STATUS_OPLOCK_BREAK_IN_PROGRESS = 0x00000108,
STATUS_VOLUME_MOUNTED = 0x00000109,
STATUS_NOTIFY_CLEANUP = 0x0000010B,
STATUS_NOTIFY_ENUM_DIR = 0x0000010C,
STATUS_NO_QUOTAS_FOR_ACCOUNT = 0x0000010D,
STATUS_FILE_LOCKED_WITH_ONLY_READERS = 0x0000012A,
STATUS_FILE_LOCKED_WITH_WRITERS = 0x0000012B,
STATUS_WAIT_FOR_OPLOCK = 0x00000367,
STATUS_OBJECT_NAME_EXISTS = 0x40000000,
STATUS_BAD_CURRENT_DIRECTORY = 0x40000007,
STATUS_NO_MORE_FILES = 0x80000006,
STATUS_DEVICE_PAPER_EMPTY = 0x8000000E,
STATUS_DEVICE_POWERED_OFF = 0x8000000F,
STATUS_DEVICE_OFF_LINE = 0x80000010,
STATUS_DEVICE_BUSY = 0x80000011,
STATUS_NO_MORE_ENTRIES = 0x8000001A,
STATUS_UNSUCCESSFUL = 0xC0000001,
STATUS_NOT_IMPLEMENTED = 0xC0000002,
STATUS_INVALID_INFO_CLASS = 0xC0000003,
#ifndef _WIN32
STATUS_INVALID_HANDLE = 0xC0000008,
STATUS_INVALID_PARAMETER = 0xC000000D,
#endif
STATUS_NO_SUCH_DEVICE = 0xC000000E,
STATUS_NO_SUCH_FILE = 0xC000000F,
STATUS_INVALID_DEVICE_REQUEST = 0xC0000010,
STATUS_END_OF_FILE = 0xC0000011,
STATUS_NO_MEDIA_IN_DEVICE = 0xC0000013,
STATUS_UNRECOGNIZED_MEDIA = 0xC0000014,
STATUS_ACCESS_DENIED = 0xc0000022,
STATUS_OBJECT_NAME_INVALID = 0xC0000033,
STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034,
STATUS_OBJECT_NAME_COLLISION = 0xc0000035,
STATUS_PORT_DISCONNECTED = 0xC0000037,
STATUS_OBJECT_PATH_INVALID = 0xC0000039,
STATUS_OBJECT_PATH_NOT_FOUND = 0xC000003A,
STATUS_INVALID_PORT_HANDLE = 0xC0000042,
STATUS_DELETE_PENDING = 0xC0000056,
STATUS_DISK_FULL = 0xC000007F,
STATUS_DEVICE_NOT_READY = 0xC00000A3,
STATUS_IO_TIMEOUT = 0xC00000B5,
STATUS_FILE_IS_A_DIRECTORY = 0xC00000BA,
STATUS_NOT_SUPPORTED = 0xC00000BB,
STATUS_PRINT_QUEUE_FULL = 0xC00000C6,
STATUS_PRINT_CANCELLED = 0xC00000C8,
STATUS_DIRECTORY_NOT_EMPTY = 0xC0000101,
STATUS_FILE_CORRUPT_ERROR = 0xC0000102,
STATUS_NOT_A_DIRECTORY = 0xC0000103,
STATUS_NAME_TOO_LONG = 0xC0000106,
STATUS_CANCELLED = 0xC0000120,
STATUS_CANNOT_DELETE = 0xC0000121,
STATUS_FILE_DELETED = 0xC0000123,
STATUS_FILE_CLOSED = 0xC0000128
};
enum RDPDR_PRINTER_ANNOUNCE_FLAG
{
RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII = 0x00000001,

View File

@ -35,17 +35,27 @@
#include <freerdp/types.h>
#include <freerdp/peer.h>
typedef struct WTSVirtualChannelManager WTSVirtualChannelManager;
#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
//#include <winpr/wtsapi.h>
typedef enum _WTS_VIRTUAL_CLASS
{
WTSVirtualClientData,
WTSVirtualFileHandle,
WTSVirtualChannelReady
WTSVirtualEventHandle, /* Extended */
WTSVirtualChannelReady /* Extended */
} WTS_VIRTUAL_CLASS;
#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW 0x00000000
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED 0x00000002
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH 0x00000004
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL 0x00000006
#define WTS_CHANNEL_OPTION_DYNAMIC_NO_COMPRESS 0x00000008
typedef struct WTSVirtualChannelManager WTSVirtualChannelManager;
#ifdef __cplusplus
extern "C" {
#endif
@ -55,9 +65,10 @@ extern "C" {
*/
FREERDP_API WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client);
FREERDP_API void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm);
FREERDP_API void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm,
void** fds, int* fds_count);
FREERDP_API void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, void** fds, int* fds_count);
FREERDP_API BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm);
FREERDP_API HANDLE WTSVirtualChannelManagerGetEventHandle(WTSVirtualChannelManager* vcm);
/**
* Opens a static or dynamic virtual channel and return the handle. If the
@ -69,10 +80,10 @@ FREERDP_API BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelMa
* Static virtual channels must be opened from the main thread. Dynamic virtual channels
* can be opened from any thread.
*/
FREERDP_API void* WTSVirtualChannelOpenEx(
/* __in */ WTSVirtualChannelManager* vcm,
/* __in */ const char* pVirtualName,
/* __in */ UINT32 flags);
// WINPR_API HANDLE WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags);
WINPR_API HANDLE WTSVirtualChannelManagerOpenEx(WTSVirtualChannelManager* vcm, LPSTR pVirtualName, DWORD flags);
/**
* Returns information about a specified virtual channel.
@ -80,17 +91,14 @@ FREERDP_API void* WTSVirtualChannelOpenEx(
* Servers use this function to gain access to a virtual channel file handle
* that can be used for asynchronous I/O.
*/
FREERDP_API BOOL WTSVirtualChannelQuery(
/* __in */ void* hChannelHandle,
/* __in */ WTS_VIRTUAL_CLASS WtsVirtualClass,
/* __out */ void** ppBuffer,
/* __out */ UINT32* pBytesReturned);
WINPR_API BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned);
/**
* Frees memory allocated by WTSVirtualChannelQuery
*/
FREERDP_API void WTSFreeMemory(
/* __in */ void* pMemory);
WINPR_API VOID WTSFreeMemory(PVOID pMemory);
/**
* Reads data from the server end of a virtual channel.
@ -109,27 +117,20 @@ FREERDP_API void WTSFreeMemory(
* The caller should use the file handle returned by WTSVirtualChannelQuery to
* determine whether a packet has arrived.
*/
FREERDP_API BOOL WTSVirtualChannelRead(
/* __in */ void* hChannelHandle,
/* __in */ UINT32 TimeOut,
/* __out */ BYTE* Buffer,
/* __in */ UINT32 BufferSize,
/* __out */ UINT32* pBytesRead);
WINPR_API BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead);
/**
* Writes data to the server end of a virtual channel.
*/
FREERDP_API BOOL WTSVirtualChannelWrite(
/* __in */ void* hChannelHandle,
/* __in */ BYTE* Buffer,
/* __in */ UINT32 Length,
/* __out */ UINT32* pBytesWritten);
WINPR_API BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten);
/**
* Closes an open virtual channel handle.
*/
FREERDP_API BOOL WTSVirtualChannelClose(
/* __in */ void* hChannelHandle);
WINPR_API BOOL WTSVirtualChannelClose(HANDLE hChannelHandle);
#ifdef __cplusplus
}

View File

@ -20,6 +20,8 @@
#ifndef FREERDP_CHANNEL_CLIENT_CLIPRDR_H
#define FREERDP_CHANNEL_CLIENT_CLIPRDR_H
#include <freerdp/types.h>
/**
* Client Interface
*/
@ -52,6 +54,48 @@ struct _cliprdr_client_context
#define CB_FORMAT_JPEG 0xD012
#define CB_FORMAT_GIF 0xD013
/* CLIPRDR_HEADER.msgType */
#define CB_MONITOR_READY 0x0001
#define CB_FORMAT_LIST 0x0002
#define CB_FORMAT_LIST_RESPONSE 0x0003
#define CB_FORMAT_DATA_REQUEST 0x0004
#define CB_FORMAT_DATA_RESPONSE 0x0005
#define CB_TEMP_DIRECTORY 0x0006
#define CB_CLIP_CAPS 0x0007
#define CB_FILECONTENTS_REQUEST 0x0008
#define CB_FILECONTENTS_RESPONSE 0x0009
#define CB_LOCK_CLIPDATA 0x000A
#define CB_UNLOCK_CLIPDATA 0x000B
/* CLIPRDR_HEADER.msgFlags */
#define CB_RESPONSE_OK 0x0001
#define CB_RESPONSE_FAIL 0x0002
#define CB_ASCII_NAMES 0x0004
/* CLIPRDR_CAPS_SET.capabilitySetType */
#define CB_CAPSTYPE_GENERAL 0x0001
/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */
#define CB_CAPSTYPE_GENERAL_LEN 12
/* CLIPRDR_GENERAL_CAPABILITY.version */
#define CB_CAPS_VERSION_1 0x00000001
#define CB_CAPS_VERSION_2 0x00000002
/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
#define CB_USE_LONG_FORMAT_NAMES 0x00000002
#define CB_STREAM_FILECLIP_ENABLED 0x00000004
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008
#define CB_CAN_LOCK_CLIPDATA 0x00000010
struct _CLIPRDR_FORMAT_NAME
{
UINT32 id;
char* name;
int length;
};
typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME;
/**
* Clipboard Events
*/

View File

@ -50,6 +50,7 @@ struct _NSC_MESSAGE
UINT32 height;
BYTE* data;
int scanline;
BYTE* PlaneBuffer;
UINT32 MaxPlaneSize;
BYTE* PlaneBuffers[5];
UINT32 OrgByteCount[4];

View File

@ -56,7 +56,6 @@ struct _RFX_TILE
BYTE* data;
int scanline;
BOOL allocated;
BYTE quantIdxY;
BYTE quantIdxCb;
BYTE quantIdxCr;
@ -68,6 +67,7 @@ struct _RFX_TILE
BYTE* YData;
BYTE* CbData;
BYTE* CrData;
BYTE* YCbCrData;
};
typedef struct _RFX_TILE RFX_TILE;
@ -118,6 +118,7 @@ struct _RFX_CONTEXT
{
RFX_STATE state;
BOOL encoder;
UINT16 flags;
UINT16 properties;
UINT16 width;
@ -153,7 +154,7 @@ struct _RFX_CONTEXT
};
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);

View File

@ -0,0 +1,51 @@
/**
* 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);
struct _cliprdr_server_context
{
WTSVirtualChannelManager* vcm;
psCliprdrStart Start;
psCliprdrStop Stop;
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 */

View File

@ -0,0 +1,50 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Dynamic 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_DRDYNVC_H
#define FREERDP_CHANNEL_SERVER_DRDYNVC_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/channels/wtsvc.h>
/**
* Server Interface
*/
typedef struct _drdynvc_client_context DrdynvcServerContext;
typedef struct _drdynvc_server_private DrdynvcServerPrivate;
typedef int (*psDrdynvcStart)(DrdynvcServerContext* context);
typedef int (*psDrdynvcStop)(DrdynvcServerContext* context);
struct _drdynvc_client_context
{
WTSVirtualChannelManager* vcm;
psDrdynvcStart Start;
psDrdynvcStop Stop;
DrdynvcServerPrivate* priv;
};
FREERDP_API DrdynvcServerContext* drdynvc_server_context_new(WTSVirtualChannelManager* vcm);
FREERDP_API void drdynvc_server_context_free(DrdynvcServerContext* context);
#endif /* FREERDP_CHANNEL_SERVER_DRDYNVC_H */

View File

@ -0,0 +1,51 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Device Redirection 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_RDPDR_H
#define FREERDP_CHANNEL_SERVER_RDPDR_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/channels/rdpdr.h>
/**
* Server Interface
*/
typedef struct _rdpdr_server_context RdpdrServerContext;
typedef struct _rdpdr_server_private RdpdrServerPrivate;
typedef int (*psRdpdrStart)(RdpdrServerContext* context);
typedef int (*psRdpdrStop)(RdpdrServerContext* context);
struct _rdpdr_server_context
{
WTSVirtualChannelManager* vcm;
psRdpdrStart Start;
psRdpdrStop Stop;
RdpdrServerPrivate* priv;
};
FREERDP_API RdpdrServerContext* rdpdr_server_context_new(WTSVirtualChannelManager* vcm);
FREERDP_API void rdpdr_server_context_free(RdpdrServerContext* context);
#endif /* FREERDP_CHANNEL_SERVER_RDPDR_H */

View File

@ -23,20 +23,30 @@
#include <freerdp/channels/wtsvc.h>
#include <freerdp/channels/rdpsnd.h>
typedef struct _rdpsnd_server_context RdpsndServerContext;
typedef struct _rdpsnd_server_context rdpsnd_server_context;
typedef struct _rdpsnd_server_private RdpsndServerPrivate;
typedef BOOL (*psRdpsndServerInitialize)(rdpsnd_server_context* context);
typedef void (*psRdpsndServerSelectFormat)(rdpsnd_server_context* context, int client_format_index);
typedef BOOL (*psRdpsndServerSendSamples)(rdpsnd_server_context* context, const void* buf, int nframes);
typedef BOOL (*psRdpsndServerSetVolume)(rdpsnd_server_context* context, int left, int right);
typedef BOOL (*psRdpsndServerClose)(rdpsnd_server_context* context);
typedef int (*psRdpsndStart)(RdpsndServerContext* context);
typedef int (*psRdpsndStop)(RdpsndServerContext* context);
typedef void (*psRdpsndServerActivated)(rdpsnd_server_context* context);
typedef BOOL (*psRdpsndServerInitialize)(RdpsndServerContext* context);
typedef void (*psRdpsndServerSelectFormat)(RdpsndServerContext* context, int client_format_index);
typedef BOOL (*psRdpsndServerSendSamples)(RdpsndServerContext* context, const void* buf, int nframes);
typedef BOOL (*psRdpsndServerSetVolume)(RdpsndServerContext* context, int left, int right);
typedef BOOL (*psRdpsndServerClose)(RdpsndServerContext* context);
typedef void (*psRdpsndServerActivated)(RdpsndServerContext* context);
struct _rdpsnd_server_context
{
WTSVirtualChannelManager* vcm;
psRdpsndStart Start;
psRdpsndStop Stop;
RdpsndServerPrivate* priv;
/* Server self-defined pointer. */
void* data;
@ -95,8 +105,8 @@ struct _rdpsnd_server_context
extern "C" {
#endif
FREERDP_API rdpsnd_server_context* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm);
FREERDP_API void rdpsnd_server_context_free(rdpsnd_server_context* context);
FREERDP_API RdpsndServerContext* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm);
FREERDP_API void rdpsnd_server_context_free(RdpsndServerContext* context);
#ifdef __cplusplus
}

View File

@ -390,6 +390,7 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
UINT32 MaxPlaneSize;
UINT32 MaxMessageSize;
NSC_MESSAGE* messages;
UINT32 PaddedMaxPlaneSize;
k = 0;
MaxRegionWidth = 64 * 4;
@ -430,11 +431,15 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
for (i = 0; i < *numMessages; i++)
{
messages[i].PlaneBuffers[0] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
messages[i].PlaneBuffers[1] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
messages[i].PlaneBuffers[2] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
messages[i].PlaneBuffers[3] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
messages[i].PlaneBuffers[4] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
PaddedMaxPlaneSize = messages[i].MaxPlaneSize + 32;
messages[i].PlaneBuffer = (BYTE*) BufferPool_Take(context->priv->PlanePool, PaddedMaxPlaneSize * 5);
messages[i].PlaneBuffers[0] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 0) + 16]);
messages[i].PlaneBuffers[1] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 1) + 16]);
messages[i].PlaneBuffers[2] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 2) + 16]);
messages[i].PlaneBuffers[3] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 3) + 16]);
messages[i].PlaneBuffers[4] = (BYTE*) &(messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 4) + 16]);
}
for (i = 0; i < *numMessages; i++)
@ -504,11 +509,7 @@ int nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message)
int nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message)
{
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[0]);
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[1]);
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[2]);
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[3]);
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[4]);
BufferPool_Return(context->priv->PlanePool, message->PlaneBuffer);
return 0;
}

View File

@ -153,7 +153,7 @@ void rfx_tile_init(RFX_TILE* tile)
}
}
RFX_TILE* rfx_tile_new()
RFX_TILE* rfx_decoder_tile_new()
{
RFX_TILE* tile = NULL;
@ -170,7 +170,7 @@ RFX_TILE* rfx_tile_new()
return tile;
}
void rfx_tile_free(RFX_TILE* tile)
void rfx_decoder_tile_free(RFX_TILE* tile)
{
if (tile)
{
@ -180,7 +180,29 @@ void rfx_tile_free(RFX_TILE* 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;
@ -193,13 +215,24 @@ RFX_CONTEXT* rfx_context_new(void)
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)
@ -211,9 +244,11 @@ RFX_CONTEXT* rfx_context_new(void)
* in order to allow optimized functions (SEE, NEON) to read from positions
* that are actually in front/beyond the buffer. Offset calculations are
* performed at the BufferPool_Take function calls in rfx_encode/decode.c.
*
* We then multiply by 3 to use a single, partioned buffer for all 3 channels.
*/
context->priv->BufferPool = BufferPool_New(TRUE, 8192 + 32, 16);
context->priv->BufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16);
#ifdef _WIN32
{
@ -903,14 +938,11 @@ void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message)
{
tile = message->tiles[i];
if (tile->YData)
BufferPool_Return(context->priv->BufferPool, tile->YData);
if (tile->CbData)
BufferPool_Return(context->priv->BufferPool, tile->CbData);
if (tile->CrData)
BufferPool_Return(context->priv->BufferPool, tile->CrData);
if (tile->YCbCrData)
{
BufferPool_Return(context->priv->BufferPool, tile->YCbCrData);
tile->YCbCrData = NULL;
}
ObjectPool_Return(context->priv->TilePool, (void*) tile);
}
@ -1068,7 +1100,7 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects,
{
context->numQuant = 1;
context->quants = (UINT32*) malloc(sizeof(rfx_default_quantization_values));
memcpy(context->quants, rfx_default_quantization_values, 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;
@ -1128,9 +1160,12 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects,
tile->YLen = 0;
tile->CbLen = 0;
tile->CrLen = 0;
tile->YData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
tile->CbData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
tile->CrData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
tile->YCbCrData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
tile->YData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 0) + 16]);
tile->CbData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 1) + 16]);
tile->CrData = (BYTE*) &(tile->YCbCrData[((8192 + 32) * 2) + 16]);
if (context->priv->UseThreads)
{
@ -1233,9 +1268,6 @@ RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, in
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);

View File

@ -128,6 +128,7 @@ static void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantizatio
/* stride is bytes between rows in the output buffer. */
BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int stride)
{
BYTE* pBuffer;
INT16* pSrcDst[3];
UINT32 *y_quants, *cb_quants, *cr_quants;
static const prim_size_t roi_64x64 = { 64, 64 };
@ -139,9 +140,10 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int
cb_quants = context->quants + (tile->quantIdxCb * 10);
cr_quants = context->quants + (tile->quantIdxCr * 10);
pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */
pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */
pSrcDst[2] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cr_b_buffer */
pBuffer = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
pSrcDst[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* y_r_buffer */
pSrcDst[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* cb_g_buffer */
pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* cr_b_buffer */
rfx_decode_component(context, y_quants, tile->YData, tile->YLen, pSrcDst[0]); /* YData */
@ -161,9 +163,7 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int
PROFILER_EXIT(context->priv->prof_rfx_decode_rgb);
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[0] - 16);
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[1] - 16);
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[2] - 16);
BufferPool_Return(context->priv->BufferPool, pBuffer);
return TRUE;
}

View File

@ -219,6 +219,7 @@ static void rfx_encode_component(RFX_CONTEXT* context, const UINT32* quantizatio
void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile)
{
BYTE* pBuffer;
INT16* pSrcDst[3];
int YLen, CbLen, CrLen;
UINT32 *YQuant, *CbQuant, *CrQuant;
@ -230,9 +231,10 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile)
CbQuant = context->quants + (tile->quantIdxCb * 10);
CrQuant = context->quants + (tile->quantIdxCr * 10);
pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */
pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */
pSrcDst[2] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cr_b_buffer */
pBuffer = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1);
pSrcDst[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* y_r_buffer */
pSrcDst[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* cb_g_buffer */
pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* cr_b_buffer */
PROFILER_ENTER(context->priv->prof_rfx_encode_rgb);
@ -265,7 +267,5 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile)
PROFILER_EXIT(context->priv->prof_rfx_encode_rgb);
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[0] - 16);
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[1] - 16);
BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[2] - 16);
BufferPool_Return(context->priv->BufferPool, pBuffer);
}

View File

@ -120,6 +120,7 @@ BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings)
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily */
Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress */
@ -149,6 +150,7 @@ BOOL rdp_read_extended_info_packet(wStream* s, rdpSettings* settings)
if (Stream_GetRemainingLength(s) < 10)
return FALSE;
Stream_Seek_UINT32(s); /* clientSessionId, should be set to 0 */
Stream_Read_UINT32(s, settings->PerformanceFlags); /* performanceFlags */

View File

@ -191,11 +191,15 @@ BOOL license_send(rdpLicense* license, wStream* s, BYTE type)
sec_flags = SEC_LICENSE_PKT;
wMsgSize = length - LICENSE_PACKET_HEADER_MAX_LENGTH + 4;
flags = PREAMBLE_VERSION_3_0;
/**
* Using EXTENDED_ERROR_MSG_SUPPORTED here would cause mstsc to crash when
* running in server mode! This flag seems to be incorrectly documented.
*/
flags = PREAMBLE_VERSION_3_0 | EXTENDED_ERROR_MSG_SUPPORTED;
if (!license->rdp->settings->ServerMode)
flags |= EXTENDED_ERROR_MSG_SUPPORTED;
rdp_write_header(license->rdp, s, length, MCS_GLOBAL_CHANNEL_ID);
rdp_write_security_header(s, sec_flags);

View File

@ -30,6 +30,10 @@
#include "peer.h"
#ifdef WITH_DEBUG_RDP
extern const char* DATA_PDU_TYPE_STRINGS[80];
#endif
static BOOL freerdp_peer_initialize(freerdp_peer* client)
{
client->context->rdp->settings->ServerMode = TRUE;
@ -85,6 +89,11 @@ static BOOL peer_recv_data_pdu(freerdp_peer* client, wStream* s)
if (!rdp_read_share_data_header(s, &length, &type, &share_id, &compressed_type, &compressed_len))
return FALSE;
#ifdef WITH_DEBUG_RDP
printf("recv %s Data PDU (0x%02X), length: %d\n",
type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length);
#endif
switch (type)
{
case DATA_PDU_TYPE_SYNCHRONIZE:

View File

@ -31,7 +31,7 @@
#include <freerdp/crypto/per.h>
#ifdef WITH_DEBUG_RDP
static const char* const DATA_PDU_TYPE_STRINGS[] =
const char* DATA_PDU_TYPE_STRINGS[80] =
{
"?", "?", /* 0x00 - 0x01 */
"Update", /* 0x02 */
@ -65,7 +65,7 @@ static const char* const DATA_PDU_TYPE_STRINGS[] =
"?", "?", "?", /* 0x33 - 0x35 */
"Status Info", /* 0x36 */
"Monitor Layout" /* 0x37 */
"?", "?", "?", /* 0x38 - 0x40 */
"FrameAcknowledge", "?", "?", /* 0x38 - 0x40 */
"?", "?", "?", "?", "?", "?" /* 0x41 - 0x46 */
};
#endif
@ -133,20 +133,21 @@ void rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type, UINT
Stream_Write_UINT16(s, channel_id); /* pduSource */
}
BOOL rdp_read_share_data_header(wStream* s, UINT16* length, BYTE* type, UINT32* share_id,
BYTE *compressed_type, UINT16 *compressed_len)
BOOL rdp_read_share_data_header(wStream* s, UINT16* length, BYTE* type, UINT32* shareId,
BYTE *compressedType, UINT16 *compressedLen)
{
if (Stream_GetRemainingLength(s) < 12)
return FALSE;
/* Share Data Header */
Stream_Read_UINT32(s, *share_id); /* shareId (4 bytes) */
Stream_Read_UINT32(s, *shareId); /* shareId (4 bytes) */
Stream_Seek_UINT8(s); /* pad1 (1 byte) */
Stream_Seek_UINT8(s); /* streamId (1 byte) */
Stream_Read_UINT16(s, *length); /* uncompressedLength (2 bytes) */
Stream_Read_UINT8(s, *type); /* pduType2, Data PDU Type (1 byte) */
Stream_Read_UINT8(s, *compressed_type); /* compressedType (1 byte) */
Stream_Read_UINT16(s, *compressed_len); /* compressedLength (2 bytes) */
Stream_Read_UINT8(s, *compressedType); /* compressedType (1 byte) */
Stream_Read_UINT16(s, *compressedLen); /* compressedLength (2 bytes) */
return TRUE;
}
@ -567,9 +568,8 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
}
#ifdef WITH_DEBUG_RDP
/* if (type != DATA_PDU_TYPE_UPDATE) */
DEBUG_RDP("recv %s Data PDU (0x%02X), length:%d",
type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length);
printf("recv %s Data PDU (0x%02X), length: %d\n",
type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, length);
#endif
switch (type)

View File

@ -1052,7 +1052,7 @@ int gdi_init(freerdp* instance, UINT32 flags, BYTE* buffer)
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;

View File

@ -66,7 +66,7 @@ struct mf_peer_context
//#endif
//#ifdef CHANNEL_RDPSND_SERVER
rdpsnd_server_context* rdpsnd;
RdpsndServerContext* rdpsnd;
//#endif
};

View File

@ -175,7 +175,7 @@ void mf_peer_rfx_update(freerdp_peer* client)
int mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
{
context->info = mf_info_get_instance();
context->rfx_context = rfx_context_new();
context->rfx_context = rfx_context_new(TRUE);
context->rfx_context->mode = RLGR3;
context->rfx_context->width = client->settings->DesktopWidth;
context->rfx_context->height = client->settings->DesktopHeight;

View File

@ -34,7 +34,7 @@ static const AUDIO_FORMAT supported_audio_formats[] =
{ WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, NULL }
};
static void mf_peer_rdpsnd_activated(rdpsnd_server_context* context)
static void mf_peer_rdpsnd_activated(RdpsndServerContext* context)
{
OSStatus status;
int i, j;

View File

@ -53,7 +53,7 @@ struct _AQRecorderState
UInt32 bufferByteSize;
SInt64 currentPacket;
bool isRunning;
rdpsnd_server_context* snd_context;
RdpsndServerContext* snd_context;
};

View File

@ -31,7 +31,7 @@ static const AUDIO_FORMAT test_audio_formats[] =
{ WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL }
};
static void sf_peer_rdpsnd_activated(rdpsnd_server_context* context)
static void sf_peer_rdpsnd_activated(RdpsndServerContext* context)
{
printf("RDPSND Activated\n");
}

View File

@ -49,7 +49,7 @@ static BOOL test_dump_rfx_realtime = TRUE;
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;
@ -398,10 +398,10 @@ static void* tf_debug_channel_thread_func(void* arg)
void* fd;
wStream* s;
void* buffer;
UINT32 bytes_returned = 0;
DWORD BytesReturned = 0;
testPeerContext* context = (testPeerContext*) arg;
if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == TRUE)
if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer, &BytesReturned) == TRUE)
{
fd = *((void**) buffer);
WTSFreeMemory(buffer);
@ -411,7 +411,7 @@ static void* tf_debug_channel_thread_func(void* arg)
s = Stream_New(NULL, 4096);
WTSVirtualChannelWrite(context->debug_channel, (BYTE*) "test1", 5, NULL);
WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test1", 5, NULL);
while (1)
{
@ -422,25 +422,25 @@ static void* tf_debug_channel_thread_func(void* arg)
Stream_SetPosition(s, 0);
if (WTSVirtualChannelRead(context->debug_channel, 0, Stream_Buffer(s),
Stream_Capacity(s), &bytes_returned) == FALSE)
if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR) Stream_Buffer(s),
Stream_Capacity(s), &BytesReturned) == FALSE)
{
if (bytes_returned == 0)
if (BytesReturned == 0)
break;
Stream_EnsureRemainingCapacity(s, bytes_returned);
Stream_EnsureRemainingCapacity(s, BytesReturned);
if (WTSVirtualChannelRead(context->debug_channel, 0, Stream_Buffer(s),
Stream_Capacity(s), &bytes_returned) == FALSE)
if (WTSVirtualChannelRead(context->debug_channel, 0, (PCHAR) Stream_Buffer(s),
Stream_Capacity(s), &BytesReturned) == FALSE)
{
/* should not happen */
break;
}
}
Stream_SetPosition(s, bytes_returned);
Stream_SetPosition(s, BytesReturned);
printf("got %d bytes\n", bytes_returned);
printf("got %d bytes\n", BytesReturned);
}
Stream_Free(s, TRUE);
@ -498,7 +498,7 @@ BOOL tf_peer_post_connect(freerdp_peer* client)
{
if (strncmp(client->settings->ChannelDefArray[i].Name, "rdpdbg", 6) == 0)
{
context->debug_channel = WTSVirtualChannelOpenEx(context->vcm, "rdpdbg", 0);
context->debug_channel = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdbg", 0);
if (context->debug_channel != NULL)
{
@ -580,7 +580,7 @@ void tf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
{
if (context->debug_channel)
{
WTSVirtualChannelWrite(context->debug_channel, (BYTE*) "test2", 5, NULL);
WTSVirtualChannelWrite(context->debug_channel, (PCHAR) "test2", 5, NULL);
}
}
else if ((flags & 0x4000) && code == 0x2D) /* 'x' key */

View File

@ -54,7 +54,7 @@ struct test_peer_context
audin_server_context* audin;
BOOL audin_open;
UINT32 frame_id;
rdpsnd_server_context* rdpsnd;
RdpsndServerContext* rdpsnd;
};
typedef struct test_peer_context testPeerContext;

View File

@ -26,7 +26,7 @@ int wf_rdpsnd_set_latest_peer(wfPeerContext* peer)
return 0;
}
int wf_directsound_activate(rdpsnd_server_context* context)
int wf_directsound_activate(RdpsndServerContext* context)
{
HRESULT hr;
wfInfo* wfi;

View File

@ -6,7 +6,7 @@
int wf_rdpsnd_set_latest_peer(wfPeerContext* peer);
int wf_directsound_activate(rdpsnd_server_context* context);
int wf_directsound_activate(RdpsndServerContext* context);
DWORD WINAPI wf_rdpsnd_directsound_thread(LPVOID lpParam);

View File

@ -100,7 +100,7 @@ struct wf_peer_context
HANDLE socketSemaphore;
WTSVirtualChannelManager* vcm;
rdpsnd_server_context* rdpsnd;
RdpsndServerContext* rdpsnd;
};
struct wf_server

View File

@ -46,7 +46,7 @@ static const AUDIO_FORMAT supported_audio_formats[] =
{ WAVE_FORMAT_ALAW, 2, 22050, 44100, 2, 8, 0, NULL }
};
static void wf_peer_rdpsnd_activated(rdpsnd_server_context* context)
static void wf_peer_rdpsnd_activated(RdpsndServerContext* context)
{
wfInfo* wfi;
int i, j;

View File

@ -198,7 +198,7 @@ void wf_update_encoder_reset(wfInfo* wfi)
}
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;

View File

@ -34,7 +34,7 @@ int wf_rdpsnd_set_latest_peer(wfPeerContext* peer)
}
int wf_wasapi_activate(rdpsnd_server_context* context)
int wf_wasapi_activate(RdpsndServerContext* context)
{
wchar_t * pattern = L"Stereo Mix";

View File

@ -6,7 +6,7 @@
int wf_rdpsnd_set_latest_peer(wfPeerContext* peer);
int wf_wasapi_activate(rdpsnd_server_context* context);
int wf_wasapi_activate(RdpsndServerContext* context);
int wf_wasapi_get_device_string(LPWSTR pattern, LPWSTR * deviceStr);

View File

@ -295,7 +295,7 @@ xfInfo* xf_info_init()
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;

View File

@ -321,11 +321,15 @@ typedef struct _wBufferPoolItem wBufferPoolItem;
struct _wBufferPool
{
int defaultSize;
int fixedSize;
DWORD alignment;
BOOL synchronized;
CRITICAL_SECTION lock;
int size;
int capacity;
void** array;
int aSize;
int aCapacity;
wBufferPoolItem* aArray;

View File

@ -67,9 +67,6 @@
#define CREDUIWIN_SECURE_PROMPT 0x00001000
#define CREDUIWIN_PACK_32_WOW 0x10000000
typedef HANDLE HWND;
typedef HANDLE HBITMAP;
typedef struct _CREDUI_INFOA
{
DWORD cbSize;

View File

@ -23,6 +23,7 @@
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/nt.h>
#include <winpr/io.h>
#include <winpr/error.h>
@ -37,30 +38,6 @@
#define INVALID_SET_FILE_POINTER ((DWORD) - 1)
#define INVALID_FILE_ATTRIBUTES ((DWORD) - 1)
#define FILE_READ_DATA 0x0001
#define FILE_LIST_DIRECTORY 0x0001
#define FILE_WRITE_DATA 0x0002
#define FILE_ADD_FILE 0x0002
#define FILE_APPEND_DATA 0x0004
#define FILE_ADD_SUBDIRECTORY 0x0004
#define FILE_CREATE_PIPE_INSTANCE 0x0004
#define FILE_READ_EA 0x0008
#define FILE_WRITE_EA 0x0010
#define FILE_EXECUTE 0x0020
#define FILE_TRAVERSE 0x0020
#define FILE_DELETE_CHILD 0x0040
#define FILE_READ_ATTRIBUTES 0x0080
#define FILE_WRITE_ATTRIBUTES 0x0100
#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF)
#define FILE_GENERIC_READ (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE)
#define FILE_GENERIC_WRITE (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE)
#define FILE_GENERIC_EXECUTE (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE)
#define FILE_SHARE_READ 0x00000001
#define FILE_SHARE_WRITE 0x00000002
#define FILE_SHARE_DELETE 0x00000004
#define FILE_ATTRIBUTE_READONLY 0x00000001
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
#define FILE_ATTRIBUTE_SYSTEM 0x00000004

View File

@ -25,24 +25,7 @@
#ifndef _WIN32
#define GENERIC_READ 0x80000000
#define GENERIC_WRITE 0x40000000
#define GENERIC_EXECUTE 0x20000000
#define GENERIC_ALL 0x10000000
#define DELETE 0x00010000
#define READ_CONTROL 0x00020000
#define WRITE_DAC 0x00040000
#define WRITE_OWNER 0x00080000
#define SYNCHRONIZE 0x00100000
#define STANDARD_RIGHTS_REQUIRED 0x000F0000
#define STANDARD_RIGHTS_READ 0x00020000
#define STANDARD_RIGHTS_WRITE 0x00020000
#define STANDARD_RIGHTS_EXECUTE 0x00020000
#define STANDARD_RIGHTS_ALL 0x001F0000
#define SPECIFIC_RIGHTS_ALL 0x0000FFFF
#define ACCESS_SYSTEM_SECURITY 0x01000000
#define MAXIMUM_ALLOWED 0x02000000
#include <winpr/nt.h>
typedef struct _OVERLAPPED
{

1405
winpr/include/winpr/nt.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,8 @@
#ifndef WINPR_UTILS_PRINT_H
#define WINPR_UTILS_PRINT_H
#include <stdio.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
@ -32,6 +34,8 @@ extern "C" {
WINPR_API void winpr_HexDump(BYTE* data, int length);
WINPR_API int wprintfx(const char *fmt, ...);
WINPR_API int wvprintfx(const char *fmt, va_list args);
WINPR_API int wvsnprintfx(char *buffer, size_t bufferSize, const char* fmt, va_list args);
#ifdef __cplusplus
}

View File

@ -35,6 +35,7 @@ extern "C" {
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
#include <winpr/nt.h>
#include <winpr/io.h>
#include <winpr/error.h>
@ -106,9 +107,6 @@ extern "C" {
typedef HANDLE HKEY;
typedef HANDLE* PHKEY;
typedef DWORD ACCESS_MASK;
typedef ACCESS_MASK* PACCESS_MASK;
typedef ACCESS_MASK REGSAM;
#define HKEY_CLASSES_ROOT ((HKEY) (LONG_PTR) (LONG) 0x80000000)

View File

@ -30,12 +30,7 @@
#ifndef _WIN32
typedef struct _LSA_UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;
#include <winpr/nt.h>
#define SECURITY_MANDATORY_UNTRUSTED_RID 0x0000
#define SECURITY_MANDATORY_LOW_RID 0x1000

166
winpr/include/winpr/wlog.h Normal file
View File

@ -0,0 +1,166 @@
/**
* WinPR: Windows Portable Runtime
* WinPR Logger
*
* 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 WINPR_LOG_H
#define WINPR_LOG_H
#include <stdio.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
typedef struct _wLog wLog;
typedef struct _wLogMessage wLogMessage;
typedef struct _wLogLayout wLogLayout;
typedef struct _wLogAppender wLogAppender;
/**
* Log Levels
*/
#define WLOG_TRACE 0
#define WLOG_DEBUG 1
#define WLOG_INFO 2
#define WLOG_WARN 3
#define WLOG_ERROR 4
#define WLOG_FATAL 5
#define WLOG_OFF 6
/**
* Log Message
*/
#define WLOG_MESSAGE_STRING 0
struct _wLogMessage
{
DWORD Type;
DWORD Level;
LPSTR PrefixString;
LPSTR FormatString;
LPSTR TextString;
DWORD LineNumber; /* __LINE__ */
LPCSTR FileName; /* __FILE__ */
LPCSTR FunctionName; /* __FUNCTION__ */
};
/**
* Log Layout
*/
struct _wLogLayout
{
DWORD Type;
LPSTR FormatString;
};
/**
* Log Appenders
*/
#define WLOG_APPENDER_CONSOLE 0
#define WLOG_APPENDER_FILE 1
typedef int (*WLOG_APPENDER_OPEN_FN)(wLog* log, wLogAppender* appender);
typedef int (*WLOG_APPENDER_CLOSE_FN)(wLog* log, wLogAppender* appender);
typedef int (*WLOG_APPENDER_WRITE_MESSAGE_FN)(wLog* log, wLogAppender* appender, wLogMessage* message);
#define WLOG_APPENDER_COMMON() \
DWORD Type; \
wLogLayout* Layout; \
WLOG_APPENDER_OPEN_FN Open; \
WLOG_APPENDER_CLOSE_FN Close; \
WLOG_APPENDER_WRITE_MESSAGE_FN WriteMessage
struct _wLogAppender
{
WLOG_APPENDER_COMMON();
};
#define WLOG_CONSOLE_STDOUT 1
#define WLOG_CONSOLE_STDERR 2
struct _wLogConsoleAppender
{
WLOG_APPENDER_COMMON();
int outputStream;
};
typedef struct _wLogConsoleAppender wLogConsoleAppender;
struct _wLogFileAppender
{
WLOG_APPENDER_COMMON();
char* FileName;
FILE* FileDescriptor;
};
typedef struct _wLogFileAppender wLogFileAppender;
/**
* Logger
*/
struct _wLog
{
LPSTR Name;
DWORD Level;
wLogAppender* Appender;
};
WINPR_API void WLog_PrintMessage(wLog* log, wLogMessage* message, ...);
#define WLog_Print(_log, _log_level, _fmt, ...) \
if (_log_level <= _log->Level) { \
wLogMessage _log_message; \
_log_message.Type = WLOG_MESSAGE_STRING; \
_log_message.Level = _log_level; \
_log_message.FormatString = _fmt; \
_log_message.LineNumber = __LINE__; \
_log_message.FileName = __FILE__; \
_log_message.FunctionName = __FUNCTION__; \
WLog_PrintMessage(_log, &(_log_message), ## __VA_ARGS__ ); \
}
WINPR_API DWORD WLog_GetLogLevel(wLog* log);
WINPR_API void WLog_SetLogLevel(wLog* log, DWORD logLevel);
WINPR_API wLogAppender* WLog_GetLogAppender(wLog* log);
WINPR_API void WLog_SetLogAppenderType(wLog* log, DWORD logAppenderType);
WINPR_API int WLog_OpenAppender(wLog* log);
WINPR_API int WLog_CloseAppender(wLog* log);
WINPR_API void WLog_ConsoleAppender_SetOutputStream(wLog* log, wLogConsoleAppender* appender, int outputStream);
WINPR_API void WLog_FileAppender_SetOutputFileName(wLog* log, wLogFileAppender* appender, const char* filename);
WINPR_API wLogLayout* WLog_GetLogLayout(wLog* log);
WINPR_API void WLog_Layout_SetPrefixFormat(wLog* log, wLogLayout* layout, const char* format);
WINPR_API wLog* WLog_New(LPCSTR name);
WINPR_API void WLog_Free(wLog* log);
#endif /* WINPR_WLOG_H */

1094
winpr/include/winpr/wtsapi.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -83,6 +83,8 @@ typedef short SHORT;
typedef void* HANDLE, *PHANDLE, *LPHANDLE;
typedef HANDLE HINSTANCE;
typedef HANDLE HMODULE;
typedef HANDLE HWND;
typedef HANDLE HBITMAP;
typedef DWORD HCALL;
typedef int INT, *LPINT;
@ -113,7 +115,6 @@ typedef WCHAR* LPWSTR, *PWSTR, *LPWCH;
typedef const WCHAR *LPCWSTR,*PCWSTR;
typedef unsigned __int64 QWORD;
typedef UCHAR* STRING;
typedef unsigned int UINT;
typedef unsigned char UINT8;
@ -158,6 +159,9 @@ typedef struct _LUID
LONG HighPart;
} LUID, *PLUID;
typedef GUID IID;
typedef IID* REFIID;
#ifdef UNICODE
#define _T(x) L ## x
#else

View File

@ -0,0 +1,49 @@
# WinPR: Windows Portable Runtime
# libwinpr-com cmake build script
#
# 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.
set(MODULE_NAME "winpr-com")
set(MODULE_PREFIX "WINPR_COM")
set(${MODULE_PREFIX}_SRCS
com.c)
if(MSVC AND (NOT MONOLITHIC_BUILD))
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def)
endif()
add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
MONOLITHIC ${MONOLITHIC_BUILD}
SOURCES ${${MODULE_PREFIX}_SRCS})
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib")
if(WIN32)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} credui)
endif()
if(MONOLITHIC_BUILD)
set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)
else()
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR")
if(BUILD_TESTING)
add_subdirectory(test)
endif()

View File

@ -0,0 +1,9 @@
set(MINWIN_LAYER "1")
set(MINWIN_GROUP "core")
set(MINWIN_MAJOR_VERSION "1")
set(MINWIN_MINOR_VERSION "0")
set(MINWIN_SHORT_NAME "com")
set(MINWIN_LONG_NAME "Component Object Model (COM)")
set(MODULE_LIBRARY_NAME "api-ms-win-${MINWIN_GROUP}-${MINWIN_SHORT_NAME}-l${MINWIN_LAYER}-${MINWIN_MAJOR_VERSION}-${MINWIN_MINOR_VERSION}")

115
winpr/libwinpr/com/com.c Normal file
View File

@ -0,0 +1,115 @@
/**
* WinPR: Windows Portable Runtime
* Component Object Model (COM)
*
* 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>
/**
* api-ms-win-core-com-l1-1-0.dll:
*
* CLSIDFromProgID
* CLSIDFromString
* CoAddRefServerProcess
* CoAllowUnmarshalerCLSID
* CoCancelCall
* CoCopyProxy
* CoCreateFreeThreadedMarshaler
* CoCreateGuid
* CoCreateInstance
* CoCreateInstanceEx
* CoCreateInstanceFromApp
* CoDecodeProxy
* CoDecrementMTAUsage
* CoDisableCallCancellation
* CoDisconnectContext
* CoDisconnectObject
* CoEnableCallCancellation
* CoFreeUnusedLibraries
* CoFreeUnusedLibrariesEx
* CoGetApartmentType
* CoGetCallContext
* CoGetCallerTID
* CoGetCancelObject
* CoGetClassObject
* CoGetContextToken
* CoGetCurrentLogicalThreadId
* CoGetCurrentProcess
* CoGetDefaultContext
* CoGetInterfaceAndReleaseStream
* CoGetMalloc
* CoGetMarshalSizeMax
* CoGetObjectContext
* CoGetPSClsid
* CoGetStandardMarshal
* CoGetStdMarshalEx
* CoGetTreatAsClass
* CoImpersonateClient
* CoIncrementMTAUsage
* CoInitializeEx
* CoInitializeSecurity
* CoInvalidateRemoteMachineBindings
* CoIsHandlerConnected
* CoLockObjectExternal
* CoMarshalHresult
* CoMarshalInterface
* CoMarshalInterThreadInterfaceInStream
* CoQueryAuthenticationServices
* CoQueryClientBlanket
* CoQueryProxyBlanket
* CoRegisterClassObject
* CoRegisterPSClsid
* CoRegisterSurrogate
* CoReleaseMarshalData
* CoReleaseServerProcess
* CoResumeClassObjects
* CoRevertToSelf
* CoRevokeClassObject
* CoSetCancelObject
* CoSetProxyBlanket
* CoSuspendClassObjects
* CoSwitchCallContext
* CoTaskMemAlloc
* CoTaskMemFree
* CoTaskMemRealloc
* CoTestCancel
* CoUninitialize
* CoUnmarshalHresult
* CoUnmarshalInterface
* CoWaitForMultipleHandles
* CoWaitForMultipleObjects
* CreateStreamOnHGlobal
* FreePropVariantArray
* GetHGlobalFromStream
* IIDFromString
* ProgIDFromCLSID
* PropVariantClear
* PropVariantCopy
* StringFromCLSID
* StringFromGUID2
* StringFromIID
*/
#ifndef _WIN32
#endif

View File

@ -0,0 +1,2 @@
LIBRARY "libwinpr-com"
EXPORTS

3
winpr/libwinpr/com/test/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
TestCom
TestCom.c

View File

@ -0,0 +1,31 @@
set(MODULE_NAME "TestCom")
set(MODULE_PREFIX "TEST_COM")
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS
TestComReference.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}
${${MODULE_PREFIX}_TESTS})
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-crt winpr-com)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
foreach(test ${${MODULE_PREFIX}_TESTS})
get_filename_component(TestName ${test} NAME_WE)
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")

View File

@ -0,0 +1,8 @@
#include <winpr/crt.h>
int TestComReference(int argc, char* argv[])
{
return 0;
}

View File

@ -31,10 +31,20 @@ add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL
MODULE winpr
MODULES winpr-nt)
if(MONOLITHIC_BUILD)
else()
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR")
if(BUILD_TESTING)
add_subdirectory(test)
endif()

View File

@ -23,25 +23,12 @@
#include <winpr/error.h>
/**
* api-ms-win-core-errorhandling-l1-1-1.dll:
*
* GetErrorMode
* SetErrorMode
* GetLastError
* SetLastError
* RestoreLastError
* RaiseException
* UnhandledExceptionFilter
* SetUnhandledExceptionFilter
* AddVectoredExceptionHandler
* RemoveVectoredExceptionHandler
* AddVectoredContinueHandler
* RemoveVectoredContinueHandler
*/
#ifndef _WIN32
#include <stdio.h>
#include <winpr/nt.h>
UINT GetErrorMode(void)
{
return 0;
@ -54,12 +41,12 @@ UINT SetErrorMode(UINT uMode)
DWORD GetLastError(VOID)
{
return 0;
return NtCurrentTeb()->LastErrorValue;
}
VOID SetLastError(DWORD dwErrCode)
{
NtCurrentTeb()->LastErrorValue = dwErrCode;
}
VOID RestoreLastError(DWORD dwErrCode)

3
winpr/libwinpr/error/test/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
TestError
TestError.c

View File

@ -0,0 +1,31 @@
set(MODULE_NAME "TestError")
set(MODULE_PREFIX "TEST_ERROR")
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS
TestErrorSetLastError.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}
${${MODULE_PREFIX}_TESTS})
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-crt winpr-synch winpr-thread winpr-error)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
foreach(test ${${MODULE_PREFIX}_TESTS})
get_filename_component(TestName ${test} NAME_WE)
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")

View File

@ -0,0 +1,89 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/error.h>
static int status = 0;
static DWORD errors[4] =
{
ERROR_INVALID_DATA,
ERROR_BROKEN_PIPE,
ERROR_INVALID_NAME,
ERROR_BAD_ARGUMENTS
};
static void* test_error_thread(void* arg)
{
int id;
DWORD error;
id = (int) (size_t) arg;
error = errors[id];
SetLastError(error);
Sleep(10);
error = GetLastError();
if (error != errors[id])
{
printf("GetLastError() failure (thread %d): Expected: 0x%04X, Actual: 0x%04X\n",
id, errors[id], error);
if (!status)
status = -1;
return NULL;
}
return NULL;
}
int TestErrorSetLastError(int argc, char* argv[])
{
DWORD error;
HANDLE threads[4];
SetLastError(ERROR_ACCESS_DENIED);
error = GetLastError();
if (error != ERROR_ACCESS_DENIED)
{
printf("GetLastError() failure: Expected: 0x%04X, Actual: 0x%04X\n",
ERROR_ACCESS_DENIED, error);
return -1;
}
threads[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) test_error_thread, (void*) (size_t) 0, 0, NULL);
threads[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) test_error_thread, (void*) (size_t) 1, 0, NULL);
threads[2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) test_error_thread, (void*) (size_t) 2, 0, NULL);
threads[3] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) test_error_thread, (void*) (size_t) 3, 0, NULL);
WaitForSingleObject(threads[0], INFINITE);
WaitForSingleObject(threads[1], INFINITE);
WaitForSingleObject(threads[2], INFINITE);
WaitForSingleObject(threads[3], INFINITE);
CloseHandle(threads[0]);
CloseHandle(threads[1]);
CloseHandle(threads[2]);
CloseHandle(threads[3]);
error = GetLastError();
if (error != ERROR_ACCESS_DENIED)
{
printf("GetLastError() failure: Expected: 0x%04X, Actual: 0x%04X\n",
ERROR_ACCESS_DENIED, error);
return -1;
}
return status;
}

View File

@ -31,7 +31,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SO
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL
MODULE winpr
MODULES winpr-crt winpr-handle winpr-path)
MODULES winpr-crt winpr-handle winpr-path winpr-synch)
if(MONOLITHIC_BUILD)

View File

@ -24,6 +24,7 @@
#include <winpr/crt.h>
#include <winpr/path.h>
#include <winpr/handle.h>
#include <winpr/platform.h>
#include <winpr/file.h>
@ -124,6 +125,21 @@
* http://download.microsoft.com/download/4/3/8/43889780-8d45-4b2e-9d3a-c696a890309f/File%20System%20Behavior%20Overview.pdf
*/
/**
* Asynchronous I/O - The GNU C Library:
* http://www.gnu.org/software/libc/manual/html_node/Asynchronous-I_002fO.html
*/
/**
* aio.h - asynchronous input and output:
* http://pubs.opengroup.org/onlinepubs/009695399/basedefs/aio.h.html
*/
/**
* Asynchronous I/O User Guide:
* http://code.google.com/p/kernel/wiki/AIOUserGuide
*/
#ifndef _WIN32
#ifdef HAVE_UNISTD_H
@ -142,6 +158,14 @@
#include <sys/stat.h>
#include <sys/socket.h>
#ifdef HAVE_AIO_H
#undef HAVE_AIO_H /* disable for now, incomplete */
#endif
#ifdef HAVE_AIO_H
#include <aio.h>
#endif
#ifdef ANDROID
#include <sys/vfs.h>
#else
@ -184,6 +208,7 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
pNamedPipe->nOutBufferSize = 0;
pNamedPipe->nInBufferSize = 0;
pNamedPipe->nDefaultTimeOut = 0;
pNamedPipe->dwFlagsAndAttributes = dwFlagsAndAttributes;
pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpFileName);
pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpFileName);
@ -255,20 +280,66 @@ BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
pipe = (WINPR_NAMED_PIPE*) Object;
status = nNumberOfBytesToRead;
if (pipe->clientfd != -1)
status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead);
else
return FALSE;
if (status < 0)
if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
{
*lpNumberOfBytesRead = 0;
return FALSE;
}
status = nNumberOfBytesToRead;
*lpNumberOfBytesRead = status;
if (pipe->clientfd == -1)
return FALSE;
status = read(pipe->clientfd, lpBuffer, nNumberOfBytesToRead);
if (status < 0)
{
*lpNumberOfBytesRead = 0;
return FALSE;
}
*lpNumberOfBytesRead = status;
}
else
{
/* Overlapped I/O */
if (!lpOverlapped)
return FALSE;
if (pipe->clientfd == -1)
return FALSE;
pipe->lpOverlapped = lpOverlapped;
#ifdef HAVE_AIO_H
{
struct aiocb cb;
ZeroMemory(&cb, sizeof(struct aiocb));
cb.aio_nbytes = nNumberOfBytesToRead;
cb.aio_fildes = pipe->clientfd;
cb.aio_offset = lpOverlapped->Offset;
cb.aio_buf = lpBuffer;
status = aio_read(&cb);
printf("aio_read status: %d\n", status);
if (status < 0)
{
return FALSE;
}
}
#else
/* synchronous behavior */
lpOverlapped->Internal = 0;
lpOverlapped->InternalHigh = (ULONG_PTR) nNumberOfBytesToRead;
lpOverlapped->Pointer = (PVOID) lpBuffer;
SetEvent(lpOverlapped->hEvent);
#endif
}
return TRUE;
}
@ -317,20 +388,66 @@ BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
pipe = (WINPR_NAMED_PIPE*) Object;
status = nNumberOfBytesToWrite;
if (pipe->clientfd != -1)
status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite);
else
return FALSE;
if (status < 0)
if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
{
*lpNumberOfBytesWritten = 0;
return FALSE;
}
status = nNumberOfBytesToWrite;
*lpNumberOfBytesWritten = status;
if (pipe->clientfd == -1)
return FALSE;
status = write(pipe->clientfd, lpBuffer, nNumberOfBytesToWrite);
if (status < 0)
{
*lpNumberOfBytesWritten = 0;
return FALSE;
}
*lpNumberOfBytesWritten = status;
}
else
{
/* Overlapped I/O */
if (!lpOverlapped)
return FALSE;
if (pipe->clientfd == -1)
return FALSE;
pipe->lpOverlapped = lpOverlapped;
#ifdef HAVE_AIO_H
{
struct aiocb cb;
ZeroMemory(&cb, sizeof(struct aiocb));
cb.aio_nbytes = nNumberOfBytesToWrite;
cb.aio_fildes = pipe->clientfd;
cb.aio_offset = lpOverlapped->Offset;
cb.aio_buf = lpBuffer;
status = aio_write(&cb);
printf("aio_write status: %d\n", status);
if (status < 0)
{
return FALSE;
}
}
#else
/* synchronous behavior */
lpOverlapped->Internal = 1;
lpOverlapped->InternalHigh = (ULONG_PTR) nNumberOfBytesToWrite;
lpOverlapped->Pointer = (PVOID) lpBuffer;
SetEvent(lpOverlapped->hEvent);
#endif
}
return TRUE;
}

View File

@ -23,25 +23,69 @@
#include <winpr/io.h>
/**
* api-ms-win-core-io-l1-1-1.dll:
*
* GetOverlappedResult
* GetOverlappedResultEx
* DeviceIoControl
* CreateIoCompletionPort
* GetQueuedCompletionStatus
* GetQueuedCompletionStatusEx
* PostQueuedCompletionStatus
* CancelIo
* CancelIoEx
* CancelSynchronousIo
*/
#ifndef _WIN32
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include "../handle/handle.h"
#include "../pipe/pipe.h"
BOOL GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait)
{
ULONG Type;
PVOID Object;
if (!winpr_Handle_GetInfo(hFile, &Type, &Object))
return FALSE;
else if (Type == HANDLE_TYPE_NAMED_PIPE)
{
int status;
DWORD request;
PVOID lpBuffer;
DWORD nNumberOfBytes;
WINPR_NAMED_PIPE* pipe;
pipe = (WINPR_NAMED_PIPE*) Object;
if (!(pipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED))
return FALSE;
if (pipe->clientfd == -1)
return FALSE;
lpBuffer = lpOverlapped->Pointer;
request = (DWORD) lpOverlapped->Internal;
nNumberOfBytes = (DWORD) lpOverlapped->InternalHigh;
if (request == 0)
{
status = read(pipe->clientfd, lpBuffer, nNumberOfBytes);
}
else
{
status = write(pipe->clientfd, lpBuffer, nNumberOfBytes);
}
if (status < 0)
{
*lpNumberOfBytesTransferred = 0;
return FALSE;
}
*lpNumberOfBytesTransferred = status;
}
return TRUE;
}

View File

@ -0,0 +1,53 @@
# WinPR: Windows Portable Runtime
# libwinpr-nt 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.
set(MODULE_NAME "winpr-nt")
set(MODULE_PREFIX "WINPR_NT")
set(${MODULE_PREFIX}_SRCS
nt.c)
if(MSVC AND (NOT MONOLITHIC_BUILD))
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def)
endif()
add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
MONOLITHIC ${MONOLITHIC_BUILD}
SOURCES ${${MODULE_PREFIX}_SRCS})
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib")
set(${MODULE_PREFIX}_LIBS
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_DL_LIBS})
if(${CMAKE_SYSTEM_NAME} MATCHES SunOS)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} rt)
endif()
if(MONOLITHIC_BUILD)
set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)
else()
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR")
if(BUILD_TESTING)
add_subdirectory(test)
endif()

View File

@ -0,0 +1,8 @@
set(MINWIN_LAYER "0")
set(MINWIN_GROUP "none")
set(MINWIN_MAJOR_VERSION "0")
set(MINWIN_MINOR_VERSION "0")
set(MINWIN_SHORT_NAME "nt")
set(MINWIN_LONG_NAME "Windows Native System Services")
set(MODULE_LIBRARY_NAME "${MINWIN_SHORT_NAME}")

View File

@ -0,0 +1,3 @@
LIBRARY "libwinpr-nt"
EXPORTS

387
winpr/libwinpr/nt/nt.c Normal file
View File

@ -0,0 +1,387 @@
/**
* WinPR: Windows Portable Runtime
* Windows Native System Services
*
* 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/nt.h>
/**
* NtXxx Routines:
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff557720/
*/
#ifndef _WIN32
#include <pthread.h>
#include <winpr/crt.h>
/**
* The current implementation of NtCurrentTeb() is not the most efficient
* but it's a starting point. Beware of potential performance bottlenecks
* caused by multithreaded usage of SetLastError/GetLastError.
*/
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static PPEB g_ProcessEnvironmentBlock = NULL;
static void NtThreadEnvironmentBlockFree(PTEB teb);
static void NtProcessEnvironmentBlockFree(PPEB peb);
static PTEB NtThreadEnvironmentBlockNew()
{
PTEB teb = NULL;
pthread_key_t key;
teb = (PTEB) malloc(sizeof(TEB));
if (teb)
{
ZeroMemory(teb, sizeof(TEB));
/**
* We are not really using the key, but it provides an automatic way
* of calling NtThreadEnvironmentBlockFree on thread termination for
* the current Thread Environment Block.
*/
pthread_key_create(&key, (void (*)(void*)) NtThreadEnvironmentBlockFree);
pthread_setspecific(key, (void*) teb);
}
return teb;
}
static void NtThreadEnvironmentBlockFree(PTEB teb)
{
DWORD index;
PPEB peb = NULL;
peb = teb->ProcessEnvironmentBlock;
pthread_mutex_lock(&mutex);
for (index = 0; index < peb->ThreadArraySize; index++)
{
if (peb->Threads[index].ThreadEnvironmentBlock == teb)
{
peb->Threads[index].ThreadId = 0;
peb->Threads[index].ThreadEnvironmentBlock = NULL;
peb->ThreadCount--;
break;
}
}
if (!peb->ThreadCount)
{
NtProcessEnvironmentBlockFree(peb);
}
pthread_mutex_unlock(&mutex);
free(teb);
}
static PPEB NtProcessEnvironmentBlockNew()
{
PPEB peb = NULL;
peb = (PPEB) malloc(sizeof(PEB));
if (peb)
{
ZeroMemory(peb, sizeof(PEB));
peb->ThreadCount = 0;
peb->ThreadArraySize = 64;
peb->Threads = (THREAD_BLOCK_ID*) malloc(sizeof(THREAD_BLOCK_ID) * peb->ThreadArraySize);
if (peb->Threads)
{
ZeroMemory(peb->Threads, sizeof(THREAD_BLOCK_ID) * peb->ThreadArraySize);
}
}
return peb;
}
static void NtProcessEnvironmentBlockFree(PPEB peb)
{
if (peb)
{
free(peb->Threads);
free(peb);
}
g_ProcessEnvironmentBlock = NULL;
}
PPEB NtCurrentPeb(void)
{
PPEB peb = NULL;
pthread_mutex_lock(&mutex);
if (!g_ProcessEnvironmentBlock)
g_ProcessEnvironmentBlock = NtProcessEnvironmentBlockNew();
peb = g_ProcessEnvironmentBlock;
pthread_mutex_unlock(&mutex);
return peb;
}
PTEB NtCurrentTeb(void)
{
DWORD index;
int freeIndex;
DWORD ThreadId;
PPEB peb = NULL;
PTEB teb = NULL;
peb = NtCurrentPeb();
ThreadId = (DWORD) pthread_self();
freeIndex = -1;
pthread_mutex_lock(&mutex);
for (index = 0; index < peb->ThreadArraySize; index++)
{
if (!peb->Threads[index].ThreadId)
{
if (freeIndex < 0)
freeIndex = (int) index;
}
if (peb->Threads[index].ThreadId == ThreadId)
{
teb = peb->Threads[index].ThreadEnvironmentBlock;
break;
}
}
if (!teb)
{
if (freeIndex >= 0)
{
teb = NtThreadEnvironmentBlockNew();
peb->Threads[freeIndex].ThreadEnvironmentBlock = teb;
peb->Threads[freeIndex].ThreadId = ThreadId;
peb->ThreadCount++;
teb->ProcessEnvironmentBlock = peb;
teb->LastErrorValue = 0;
}
}
pthread_mutex_unlock(&mutex);
return teb;
}
/**
* RtlInitAnsiString routine:
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff561918/
*/
VOID RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
{
DestinationString->Buffer = (PCHAR) SourceString;
if (!SourceString)
{
DestinationString->Length = 0;
DestinationString->MaximumLength = 0;
}
else
{
USHORT length = (USHORT) strlen(SourceString);
DestinationString->Length = length;
DestinationString->MaximumLength = length + 1;
}
}
/**
* RtlInitUnicodeString routine:
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff561934/
*/
VOID RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
{
DestinationString->Buffer = (PWSTR) SourceString;
if (!SourceString)
{
DestinationString->Length = 0;
DestinationString->MaximumLength = 0;
}
else
{
USHORT length = (USHORT) _wcslen(SourceString);
DestinationString->Length = length * 2;
DestinationString->MaximumLength = (length + 1) * 2;
}
}
/**
* RtlAnsiStringToUnicodeString function:
* http://msdn.microsoft.com/en-us/library/ms648413/
*/
NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString,
PCANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
{
int index;
if (!SourceString)
{
RtlInitUnicodeString(DestinationString, NULL);
return 0;
}
if (AllocateDestinationString)
{
DestinationString->Length = SourceString->Length * 2;
DestinationString->MaximumLength = SourceString->MaximumLength * 2;
DestinationString->Buffer = (PWSTR) malloc(DestinationString->MaximumLength);
for (index = 0; index < SourceString->MaximumLength; index++)
{
DestinationString->Buffer[index] = (WCHAR) SourceString->Buffer[index];
}
}
else
{
}
return 0;
}
/**
* RtlFreeUnicodeString function:
* http://msdn.microsoft.com/en-us/library/ms648418/
*/
VOID RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
{
if (UnicodeString)
{
if (UnicodeString->Buffer)
free(UnicodeString->Buffer);
UnicodeString->Length = 0;
UnicodeString->MaximumLength = 0;
}
}
/**
* RtlNtStatusToDosError function:
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms680600/
*/
ULONG RtlNtStatusToDosError(NTSTATUS status)
{
return status;
}
/**
* InitializeObjectAttributes macro
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff547804/
*/
VOID InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes,
PUNICODE_STRING ObjectName, ULONG Attributes, HANDLE RootDirectory,
PSECURITY_DESCRIPTOR SecurityDescriptor)
{
InitializedAttributes->Length = sizeof(OBJECT_ATTRIBUTES);
InitializedAttributes->ObjectName = ObjectName;
InitializedAttributes->Attributes = Attributes;
InitializedAttributes->RootDirectory = RootDirectory;
InitializedAttributes->SecurityDescriptor = SecurityDescriptor;
InitializedAttributes->SecurityQualityOfService = NULL;
}
/**
* NtCreateFile function:
* http://msdn.microsoft.com/en-us/library/bb432380/
*/
NTSTATUS NtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock,
PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess,
ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength)
{
return 0;
}
/**
* NtOpenFile function:
* http://msdn.microsoft.com/en-us/library/bb432381/
*/
NTSTATUS NtOpenFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock,
ULONG ShareAccess, ULONG OpenOptions)
{
return 0;
}
/**
* NtDeviceIoControlFile function:
* http://msdn.microsoft.com/en-us/library/ms648411/
*/
NTSTATUS NtDeviceIoControlFile(HANDLE FileHandle, HANDLE Event,
PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock,
ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength,
PVOID OutputBuffer, ULONG OutputBufferLength)
{
return 0;
}
/**
* NtClose function:
* http://msdn.microsoft.com/en-us/library/ms648410/
*/
NTSTATUS NtClose(HANDLE Handle)
{
return 0;
}
/**
* NtWaitForSingleObject function:
* http://msdn.microsoft.com/en-us/library/ms648412/
*/
NTSTATUS NtWaitForSingleObject(HANDLE Handle, BOOLEAN Alertable, PLARGE_INTEGER Timeout)
{
return 0;
}
#endif

3
winpr/libwinpr/nt/test/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
TestNt
TestNt.c

View File

@ -0,0 +1,32 @@
set(MODULE_NAME "TestNt")
set(MODULE_PREFIX "TEST_NT")
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS
TestNtCreateFile.c
TestNtCurrentTeb.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}
${${MODULE_PREFIX}_TESTS})
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-crt winpr-nt)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
foreach(test ${${MODULE_PREFIX}_TESTS})
get_filename_component(TestName ${test} NAME_WE)
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")

View File

@ -0,0 +1,30 @@
#include <winpr/crt.h>
#include <winpr/nt.h>
int TestNtCreateFile(int argc, char* argv[])
{
HANDLE handle;
NTSTATUS ntstatus;
ULONG CreateOptions;
ANSI_STRING aString;
UNICODE_STRING uString;
ACCESS_MASK DesiredAccess = 0;
OBJECT_ATTRIBUTES attributes;
IO_STATUS_BLOCK ioStatusBlock;
RtlInitAnsiString(&aString, "\\Device\\FreeRDP\\TEST");
RtlAnsiStringToUnicodeString(&uString, &aString, TRUE);
InitializeObjectAttributes(&attributes, NULL, 0, NULL, NULL);
DesiredAccess = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE;
CreateOptions = FILE_DIRECTORY_FILE | FILE_WRITE_THROUGH;
ntstatus = NtCreateFile(&handle, DesiredAccess, &attributes, &ioStatusBlock, 0, 0, 0, CreateOptions, 0, 0, 0);
RtlFreeUnicodeString(&uString);
return 0;
}

View File

@ -0,0 +1,20 @@
#include <stdio.h>
#include <winpr/nt.h>
int TestNtCurrentTeb(int argc, char* argv[])
{
PTEB teb;
teb = NtCurrentTeb();
if (!teb)
{
printf("NtCurrentTeb() returned NULL\n");
return -1;
}
return 0;
}

View File

@ -108,6 +108,7 @@ HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD
pNamedPipe->nOutBufferSize = nOutBufferSize;
pNamedPipe->nInBufferSize = nInBufferSize;
pNamedPipe->nDefaultTimeOut = nDefaultTimeOut;
pNamedPipe->dwFlagsAndAttributes = dwOpenMode;
pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpName);
@ -177,6 +178,14 @@ BOOL ConnectNamedPipe(HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped)
pNamedPipe->clientfd = status;
if (pNamedPipe->dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
{
if (!lpOverlapped)
return FALSE;
SetEvent(lpOverlapped->hEvent);
}
return TRUE;
}

Some files were not shown because too many files have changed in this diff Show More