Merge pull request #1574 from awakecoding/master

Refactoring, Robustness, Valgrind Fixes, WinPR
This commit is contained in:
Marc-André Moreau 2013-11-06 12:44:02 -08:00
commit 2e28621802
306 changed files with 12851 additions and 3243 deletions

4
.gitignore vendored
View File

@ -15,8 +15,10 @@ DartConfiguration.tcl
CMakeCPackOptions.cmake
_CPack_Packages
LICENSE.txt
external/*
/external/*
!external/README
*Config.cmake
*ConfigVersion.cmake
include/freerdp/version.h
*.a.objlist.cmake

View File

@ -51,6 +51,7 @@ include(ComplexLibrary)
include(FeatureSummary)
include(CheckCCompilerFlag)
include(GNUInstallDirsWrapper)
include(CMakePackageConfigHelpers)
# Soname versioning
set(FREERDP_VERSION_MAJOR "1")
@ -166,7 +167,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
endif()
if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Weverything -Wno-unused-parameter")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-macros -Wno-padded")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-c11-extensions -Wno-gnu")
if(WITH_SSE2)
@ -552,6 +553,31 @@ if(WITH_SERVER)
add_subdirectory(server)
endif()
# Exporting
if(${CMAKE_VERSION} VERSION_GREATER "2.8.10")
export(PACKAGE freerdp)
set(FREERDP_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/FreeRDP")
set(FREERDP_INCLUDE_DIR "include")
set(FREERDP_MONOLITHIC_BUILD ${MONOLITHIC_BUILD})
configure_package_config_file(FreeRDPConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FreeRDPConfig.cmake
INSTALL_DESTINATION ${FREERDP_CMAKE_INSTALL_DIR}
PATH_VARS FREERDP_INCLUDE_DIR FREERDP_MONOLITHIC_BUILD)
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/FreeRDPConfigVersion.cmake
VERSION ${FREERDP_VERSION} COMPATIBILITY SameMajorVersion)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/FreeRDPConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/FreeRDPConfigVersion.cmake
DESTINATION ${FREERDP_CMAKE_INSTALL_DIR})
install(EXPORT FreeRDPTargets DESTINATION ${FREERDP_CMAKE_INSTALL_DIR})
endif()
# Packaging
set(CMAKE_CPACK_INCLUDE_FILE "CMakeCPack.cmake")

11
FreeRDPConfig.cmake.in Normal file
View File

@ -0,0 +1,11 @@
@PACKAGE_INIT@
set(FreeRDP_VERSION_MAJOR "@FREERDP_VERSION_MAJOR@")
set(FreeRDP_VERSION_MINOR "@FREERDP_VERSION_MINOR@")
set(FreeRDP_VERSION_REVISION "@FREERDP_VERSION_REVISION@")
set(FreeRDP_MONOLITHIC_BUILD "@FREERDP_MONOLITHIC_BUILD@")
set_and_check(FreeRDP_INCLUDE_DIR "@PACKAGE_FREERDP_INCLUDE_DIR@")
include("${CMAKE_CURRENT_LIST_DIR}/FreeRDPTargets.cmake")

View File

@ -34,9 +34,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -39,3 +39,7 @@ target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
if(NOT BUILD_SHARED_LIBS)
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT FreeRDPTargets)
endif()

View File

@ -17,8 +17,8 @@
* limitations under the License.
*/
#ifndef __AUDIN_MAIN_H
#define __AUDIN_MAIN_H
#ifndef FREERDP_AUDIN_CLIENT_MAIN_H
#define FREERDP_AUDIN_CLIENT_MAIN_H
#ifdef HAVE_CONFIG_H
#include "config.h"
@ -28,6 +28,7 @@
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <freerdp/utils/debug.h>
#include <freerdp/client/audin.h>
#ifdef WITH_DEBUG_DVC
#define DEBUG_DVC(fmt, ...) DEBUG_CLASS(DVC, fmt, ## __VA_ARGS__)
@ -35,44 +36,5 @@
#define DEBUG_DVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif
typedef BOOL (*AudinReceive) (BYTE* data, int size, void* user_data);
typedef struct audin_format audinFormat;
struct audin_format
{
UINT16 wFormatTag;
UINT16 nChannels;
UINT32 nSamplesPerSec;
UINT16 nBlockAlign;
UINT16 wBitsPerSample;
UINT16 cbSize;
BYTE* data;
};
typedef struct _IAudinDevice IAudinDevice;
struct _IAudinDevice
{
void (*Open) (IAudinDevice* devplugin, AudinReceive receive, void* user_data);
BOOL (*FormatSupported) (IAudinDevice* devplugin, audinFormat* format);
void (*SetFormat) (IAudinDevice* devplugin, audinFormat* format, UINT32 FramesPerPacket);
void (*Close) (IAudinDevice* devplugin);
void (*Free) (IAudinDevice* devplugin);
};
#define AUDIN_DEVICE_EXPORT_FUNC_NAME "freerdp_audin_client_subsystem_entry"
typedef void (*PREGISTERAUDINDEVICE)(IWTSPlugin* plugin, IAudinDevice* device);
struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS
{
IWTSPlugin* plugin;
PREGISTERAUDINDEVICE pRegisterAudinDevice;
ADDIN_ARGV* args;
};
typedef struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS FREERDP_AUDIN_DEVICE_ENTRY_POINTS;
typedef FREERDP_AUDIN_DEVICE_ENTRY_POINTS* PFREERDP_AUDIN_DEVICE_ENTRY_POINTS;
typedef int (*PFREERDP_AUDIN_DEVICE_ENTRY)(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints);
#endif /* __AUDIN_MAIN_H */
#endif /* FREERDP_AUDIN_CLIENT_MAIN_H */

View File

@ -39,6 +39,4 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${OPENSLES_LIBRARIES})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)

View File

@ -36,6 +36,4 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)

View File

@ -29,4 +29,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MODULE freerdp
MODULES freerdp-codec freerdp-utils)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -74,12 +74,12 @@ CHANNEL_INIT_DATA g_ChannelInitData;
static wArrayList* g_ChannelsList = NULL;
/* To generate unique sequence for all open handles */
int g_open_handle_sequence;
int g_open_handle_sequence = 1;
/* For locking the global resources */
static HANDLE g_mutex_init;
static CRITICAL_SECTION g_channels_lock;
rdpChannels* freerdp_channels_find_by_open_handle(int open_handle, int* pindex)
rdpChannels* freerdp_channels_find_by_open_handle(int OpenHandle, int* pindex)
{
int i, j;
BOOL found = FALSE;
@ -94,7 +94,7 @@ rdpChannels* freerdp_channels_find_by_open_handle(int open_handle, int* pindex)
{
for (j = 0; j < channels->openDataCount; j++)
{
if (channels->openDataList[j].OpenHandle == open_handle)
if (channels->openDataList[j].OpenHandle == OpenHandle)
{
*pindex = j;
found = TRUE;
@ -324,21 +324,17 @@ UINT32 FreeRDP_VirtualChannelEventPush(UINT32 openHandle, wMessage* event)
*/
int freerdp_channels_global_init(void)
{
g_open_handle_sequence = 1;
g_mutex_init = CreateMutex(NULL, FALSE, NULL);
if (!g_ChannelsList)
{
g_ChannelsList = ArrayList_New(TRUE);
InitializeCriticalSectionAndSpinCount(&g_channels_lock, 4000);
}
return 0;
}
int freerdp_channels_global_uninit(void)
{
/* TODO: free channels list */
CloseHandle(g_mutex_init);
return 0;
}
@ -397,12 +393,12 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, v
channels->can_call_init = TRUE;
channels->settings = settings;
WaitForSingleObject(g_mutex_init, INFINITE);
EnterCriticalSection(&g_channels_lock);
g_ChannelInitData.channels = channels;
status = pChannelClientData->entry((PCHANNEL_ENTRY_POINTS) &ep);
ReleaseMutex(g_mutex_init);
LeaveCriticalSection(&g_channels_lock);
/* disable MyVirtualChannelInit */
channels->settings = NULL;
@ -499,22 +495,39 @@ int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance)
int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
{
int index;
char* hostname;
int hostnameLength;
char* name;
char* hostname;
int hostnameLength;
CHANNEL_CLIENT_DATA* pChannelClientData;
channels->is_connected = 1;
hostname = instance->settings->ServerHostname;
hostnameLength = strlen(hostname);
DEBUG_CHANNELS("hostname [%s] channels->num_libs [%d]", hostname, channels->clientDataCount);
for (index = 0; index < channels->clientDataCount; index++)
{
pChannelClientData = &channels->clientDataList[index];
if (pChannelClientData->pChannelInitEventProc)
{
ChannelConnectedEventArgs e;
CHANNEL_OPEN_DATA* pChannelOpenData;
pChannelOpenData = &channels->openDataList[index];
pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_CONNECTED, hostname, hostnameLength);
name = (char*) malloc(9);
CopyMemory(name, pChannelOpenData->name, 8);
name[8] = '\0';
EventArgsInit(&e, "freerdp");
e.name = name;
e.pInterface = pChannelOpenData->pInterface;
PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e);
free(name);
}
}
channels->drdynvc = (DrdynvcClientContext*) freerdp_channels_get_static_channel_interface(channels, "drdynvc");
@ -774,19 +787,37 @@ wMessage* freerdp_channels_pop_event(rdpChannels* channels)
void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
{
int index;
char* name;
CHANNEL_OPEN_DATA* pChannelOpenData;
CHANNEL_CLIENT_DATA* pChannelClientData;
DEBUG_CHANNELS("closing");
channels->is_connected = 0;
freerdp_channels_check_fds(channels, instance);
/* tell all libraries we are shutting down */
for (index = 0; index < channels->clientDataCount; index++)
{
ChannelDisconnectedEventArgs e;
pChannelClientData = &channels->clientDataList[index];
if (pChannelClientData->pChannelInitEventProc)
pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_TERMINATED, 0, 0);
pChannelOpenData = &channels->openDataList[index];
name = (char*) malloc(9);
CopyMemory(name, pChannelOpenData->name, 8);
name[8] = '\0';
EventArgsInit(&e, "freerdp");
e.name = name;
e.pInterface = pChannelOpenData->pInterface;
PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e);
free(name);
}
/* Emit a quit signal to the internal message pipe. */

View File

@ -37,8 +37,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MODULE winpr
MODULES winpr-crt)
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -32,4 +32,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -39,9 +39,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -38,5 +38,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MODULE winpr
MODULES winpr-synch)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -32,4 +32,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -45,8 +45,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -40,10 +40,9 @@
#include <winpr/crt.h>
#include <winpr/file.h>
#include <winpr/stream.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/utils/svc_plugin.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@ -125,7 +124,6 @@ static BOOL drive_file_remove_dir(const char* path)
if (STAT(p, &st) != 0)
{
DEBUG_WARN("stat %s failed.", p);
ret = FALSE;
}
else if (S_ISDIR(st.st_mode))
@ -134,7 +132,6 @@ static BOOL drive_file_remove_dir(const char* path)
}
else if (unlink(p) < 0)
{
DEBUG_WARN("unlink %s failed.", p);
ret = FALSE;
}
else
@ -156,7 +153,6 @@ static BOOL drive_file_remove_dir(const char* path)
{
if (rmdir(path) < 0)
{
DEBUG_WARN("rmdir %s failed.", path);
ret = FALSE;
}
}
@ -422,7 +418,6 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w
default:
Stream_Write_UINT32(output, 0); /* Length */
DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass);
return FALSE;
}
return TRUE;
@ -517,12 +512,10 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
/* TODO rename does not work on win32 */
if (rename(file->fullpath, fullpath) == 0)
{
DEBUG_SVC("renamed %s to %s", file->fullpath, fullpath);
drive_file_set_fullpath(file, fullpath);
}
else
{
DEBUG_WARN("rename %s to %s failed, errno = %d", file->fullpath, fullpath, errno);
free(fullpath);
return FALSE;
}
@ -530,7 +523,6 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
break;
default:
DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass);
return FALSE;
}
@ -546,8 +538,6 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
struct STAT st;
struct dirent* ent;
DEBUG_SVC("path %s FsInformationClass %d InitialQuery %d", path, FsInformationClass, InitialQuery);
if (!file->dir)
{
Stream_Write_UINT32(output, 0); /* Length */
@ -586,9 +576,8 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
ent = readdir(file->dir);
}
if (ent == NULL)
if (!ent)
{
DEBUG_SVC(" pattern %s not found.", file->pattern);
Stream_Write_UINT32(output, 0); /* Length */
Stream_Write_UINT8(output, 0); /* Padding */
return FALSE;
@ -600,10 +589,9 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
if (STAT((char*) ent_path, &st) != 0)
{
DEBUG_WARN("stat %s failed. errno = %d", (char*) ent_path, errno);
}
DEBUG_SVC(" pattern %s matched %s", file->pattern, ent_path);
free(ent_path);
ent_path = NULL;
@ -682,7 +670,6 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
default:
Stream_Write_UINT32(output, 0); /* Length */
Stream_Write_UINT8(output, 0); /* Padding */
DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass);
ret = FALSE;
break;
}

View File

@ -38,12 +38,11 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/interlocked.h>
#include <freerdp/utils/list.h>
#include <winpr/stream.h>
#include <winpr/interlocked.h>
#include <winpr/collections.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/utils/svc_plugin.h>
#include "drive_file.h"
@ -54,12 +53,10 @@ struct _DRIVE_DEVICE
DEVICE device;
char* path;
LIST* files;
wListDictionary* files;
HANDLE thread;
HANDLE irpEvent;
HANDLE stopEvent;
PSLIST_HEADER pIrpList;
wMessageQueue* IrpQueue;
DEVMAN* devman;
};
@ -94,31 +91,23 @@ static UINT32 drive_map_posix_err(int fs_errno)
break;
}
DEBUG_SVC("errno 0x%x mapped to 0x%x", fs_errno, rc);
return rc;
}
static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* disk, UINT32 id)
static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32 id)
{
LIST_ITEM* item;
DRIVE_FILE* file;
DRIVE_FILE* file = NULL;
void* key = (void*) (size_t) id;
for (item = disk->files->head; item; item = item->next)
{
file = (DRIVE_FILE*) item->data;
file = (DRIVE_FILE*) ListDictionary_GetItemValue(drive->files, key);
if (file->id == id)
return file;
}
return NULL;
return file;
}
static void drive_process_irp_create(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
{
char* path = NULL;
int status;
void* key;
UINT32 FileId;
DRIVE_FILE* file;
BYTE Information;
@ -126,6 +115,7 @@ static void drive_process_irp_create(DRIVE_DEVICE* disk, IRP* irp)
UINT32 CreateDisposition;
UINT32 CreateOptions;
UINT32 PathLength;
char* path = NULL;
Stream_Read_UINT32(irp->input, DesiredAccess);
Stream_Seek(irp->input, 16); /* AllocationSize(8), FileAttributes(4), SharedAccess(4) */
@ -141,16 +131,14 @@ static void drive_process_irp_create(DRIVE_DEVICE* disk, IRP* irp)
FileId = irp->devman->id_sequence++;
file = drive_file_new(disk->path, path, FileId,
file = drive_file_new(drive->path, path, FileId,
DesiredAccess, CreateDisposition, CreateOptions);
if (file == NULL)
if (!file)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
FileId = 0;
Information = 0;
DEBUG_WARN("failed to create %s.", path);
}
else if (file->err)
{
@ -163,7 +151,8 @@ static void drive_process_irp_create(DRIVE_DEVICE* disk, IRP* irp)
}
else
{
list_enqueue(disk->files, file);
key = (void*) (size_t) file->id;
ListDictionary_Add(drive->files, key, file);
switch (CreateDisposition)
{
@ -183,7 +172,6 @@ static void drive_process_irp_create(DRIVE_DEVICE* disk, IRP* irp)
Information = 0;
break;
}
DEBUG_SVC("%s(%d) created.", file->fullpath, file->id);
}
Stream_Write_UINT32(irp->output, FileId);
@ -194,23 +182,22 @@ static void drive_process_irp_create(DRIVE_DEVICE* disk, IRP* irp)
irp->Complete(irp);
}
static void drive_process_irp_close(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp)
{
void* key;
DRIVE_FILE* file;
file = drive_get_file_by_id(disk, irp->FileId);
file = drive_get_file_by_id(drive, irp->FileId);
if (file == NULL)
key = (void*) (size_t) irp->FileId;
if (!file)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
DEBUG_WARN("FileId %d not valid.", irp->FileId);
}
else
{
DEBUG_SVC("%s(%d) closed.", file->fullpath, file->id);
list_remove(disk->files, file);
ListDictionary_Remove(drive->files, key);
drive_file_free(file);
}
@ -219,7 +206,7 @@ static void drive_process_irp_close(DRIVE_DEVICE* disk, IRP* irp)
irp->Complete(irp);
}
static void drive_process_irp_read(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp_read(DRIVE_DEVICE* drive, IRP* irp)
{
DRIVE_FILE* file;
UINT32 Length;
@ -229,37 +216,32 @@ static void drive_process_irp_read(DRIVE_DEVICE* disk, IRP* irp)
Stream_Read_UINT32(irp->input, Length);
Stream_Read_UINT64(irp->input, Offset);
file = drive_get_file_by_id(disk, irp->FileId);
file = drive_get_file_by_id(drive, irp->FileId);
if (file == NULL)
if (!file)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
Length = 0;
DEBUG_WARN("FileId %d not valid.", irp->FileId);
}
else if (!drive_file_seek(file, Offset))
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
Length = 0;
DEBUG_WARN("seek %s(%d) failed.", file->fullpath, file->id);
}
else
{
buffer = (BYTE*) malloc(Length);
if (!drive_file_read(file, buffer, &Length))
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
free(buffer);
buffer = NULL;
Length = 0;
DEBUG_WARN("read %s(%d) failed.", file->fullpath, file->id);
}
else
{
DEBUG_SVC("read %llu-%llu from %s(%d).", Offset, Offset + Length, file->fullpath, file->id);
}
}
@ -276,7 +258,7 @@ static void drive_process_irp_read(DRIVE_DEVICE* disk, IRP* irp)
irp->Complete(irp);
}
static void drive_process_irp_write(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp)
{
DRIVE_FILE* file;
UINT32 Length;
@ -286,32 +268,26 @@ static void drive_process_irp_write(DRIVE_DEVICE* disk, IRP* irp)
Stream_Read_UINT64(irp->input, Offset);
Stream_Seek(irp->input, 20); /* Padding */
file = drive_get_file_by_id(disk, irp->FileId);
file = drive_get_file_by_id(drive, irp->FileId);
if (file == NULL)
if (!file)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
Length = 0;
DEBUG_WARN("FileId %d not valid.", irp->FileId);
}
else if (!drive_file_seek(file, Offset))
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
Length = 0;
DEBUG_WARN("seek %s(%d) failed.", file->fullpath, file->id);
}
else if (!drive_file_write(file, Stream_Pointer(irp->input), Length))
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
Length = 0;
DEBUG_WARN("write %s(%d) failed.", file->fullpath, file->id);
}
else
{
DEBUG_SVC("write %llu-%llu to %s(%d).", Offset, Offset + Length, file->fullpath, file->id);
}
Stream_Write_UINT32(irp->output, Length);
@ -320,36 +296,32 @@ static void drive_process_irp_write(DRIVE_DEVICE* disk, IRP* irp)
irp->Complete(irp);
}
static void drive_process_irp_query_information(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp_query_information(DRIVE_DEVICE* drive, IRP* irp)
{
DRIVE_FILE* file;
UINT32 FsInformationClass;
Stream_Read_UINT32(irp->input, FsInformationClass);
file = drive_get_file_by_id(disk, irp->FileId);
file = drive_get_file_by_id(drive, irp->FileId);
if (file == NULL)
if (!file)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
DEBUG_WARN("FileId %d not valid.", irp->FileId);
}
else if (!drive_file_query_information(file, FsInformationClass, irp->output))
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
DEBUG_WARN("FsInformationClass %d on %s(%d) failed.", FsInformationClass, file->fullpath, file->id);
}
else
{
DEBUG_SVC("FsInformationClass %d on %s(%d).", FsInformationClass, file->fullpath, file->id);
}
irp->Complete(irp);
}
static void drive_process_irp_set_information(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp)
{
DRIVE_FILE* file;
UINT32 FsInformationClass;
@ -359,23 +331,19 @@ static void drive_process_irp_set_information(DRIVE_DEVICE* disk, IRP* irp)
Stream_Read_UINT32(irp->input, Length);
Stream_Seek(irp->input, 24); /* Padding */
file = drive_get_file_by_id(disk, irp->FileId);
file = drive_get_file_by_id(drive, irp->FileId);
if (file == NULL)
if (!file)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
DEBUG_WARN("FileId %d not valid.", irp->FileId);
}
else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input))
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
DEBUG_WARN("FsInformationClass %d on %s(%d) failed.", FsInformationClass, file->fullpath, file->id);
}
else
{
DEBUG_SVC("FsInformationClass %d on %s(%d) ok.", FsInformationClass, file->fullpath, file->id);
}
Stream_Write_UINT32(irp->output, Length);
@ -383,7 +351,7 @@ static void drive_process_irp_set_information(DRIVE_DEVICE* disk, IRP* irp)
irp->Complete(irp);
}
static void drive_process_irp_query_volume_information(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp)
{
UINT32 FsInformationClass;
wStream* output = irp->output;
@ -396,8 +364,8 @@ static void drive_process_irp_query_volume_information(DRIVE_DEVICE* disk, IRP*
Stream_Read_UINT32(irp->input, FsInformationClass);
STATVFS(disk->path, &svfst);
STAT(disk->path, &st);
STATVFS(drive->path, &svfst);
STAT(drive->path, &st);
switch (FsInformationClass)
{
@ -470,7 +438,6 @@ static void drive_process_irp_query_volume_information(DRIVE_DEVICE* disk, IRP*
default:
irp->IoStatus = STATUS_UNSUCCESSFUL;
Stream_Write_UINT32(output, 0); /* Length */
DEBUG_WARN("invalid FsInformationClass %d", FsInformationClass);
break;
}
@ -479,20 +446,19 @@ static void drive_process_irp_query_volume_information(DRIVE_DEVICE* disk, IRP*
/* http://msdn.microsoft.com/en-us/library/cc241518.aspx */
static void drive_process_irp_silent_ignore(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp_silent_ignore(DRIVE_DEVICE* drive, IRP* irp)
{
UINT32 FsInformationClass;
wStream* output = irp->output;
Stream_Read_UINT32(irp->input, FsInformationClass);
DEBUG_SVC("FsInformationClass %d in drive_process_irp_silent_ignore", FsInformationClass);
Stream_Write_UINT32(output, 0); /* Length */
irp->Complete(irp);
}
static void drive_process_irp_query_directory(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
{
char* path = NULL;
int status;
@ -512,13 +478,12 @@ static void drive_process_irp_query_directory(DRIVE_DEVICE* disk, IRP* irp)
if (status < 1)
path = (char*) calloc(1, 1);
file = drive_get_file_by_id(disk, irp->FileId);
file = drive_get_file_by_id(drive, irp->FileId);
if (file == NULL)
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
Stream_Write_UINT32(irp->output, 0); /* Length */
DEBUG_WARN("FileId %d not valid.", irp->FileId);
}
else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path, irp->output))
{
@ -530,12 +495,12 @@ static void drive_process_irp_query_directory(DRIVE_DEVICE* disk, IRP* irp)
irp->Complete(irp);
}
static void drive_process_irp_directory_control(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp_directory_control(DRIVE_DEVICE* drive, IRP* irp)
{
switch (irp->MinorFunction)
{
case IRP_MN_QUERY_DIRECTORY:
drive_process_irp_query_directory(disk, irp);
drive_process_irp_query_directory(drive, irp);
break;
case IRP_MN_NOTIFY_CHANGE_DIRECTORY: /* TODO */
@ -543,7 +508,6 @@ static void drive_process_irp_directory_control(DRIVE_DEVICE* disk, IRP* irp)
break;
default:
DEBUG_WARN("MinorFunction 0x%X not supported", irp->MinorFunction);
irp->IoStatus = STATUS_NOT_SUPPORTED;
Stream_Write_UINT32(irp->output, 0); /* Length */
irp->Complete(irp);
@ -551,142 +515,116 @@ static void drive_process_irp_directory_control(DRIVE_DEVICE* disk, IRP* irp)
}
}
static void drive_process_irp_device_control(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp_device_control(DRIVE_DEVICE* drive, IRP* irp)
{
Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */
irp->Complete(irp);
}
static void drive_process_irp(DRIVE_DEVICE* disk, IRP* irp)
static void drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
{
irp->IoStatus = STATUS_SUCCESS;
switch (irp->MajorFunction)
{
case IRP_MJ_CREATE:
drive_process_irp_create(disk, irp);
drive_process_irp_create(drive, irp);
break;
case IRP_MJ_CLOSE:
drive_process_irp_close(disk, irp);
drive_process_irp_close(drive, irp);
break;
case IRP_MJ_READ:
drive_process_irp_read(disk, irp);
drive_process_irp_read(drive, irp);
break;
case IRP_MJ_WRITE:
drive_process_irp_write(disk, irp);
drive_process_irp_write(drive, irp);
break;
case IRP_MJ_QUERY_INFORMATION:
drive_process_irp_query_information(disk, irp);
drive_process_irp_query_information(drive, irp);
break;
case IRP_MJ_SET_INFORMATION:
drive_process_irp_set_information(disk, irp);
drive_process_irp_set_information(drive, irp);
break;
case IRP_MJ_QUERY_VOLUME_INFORMATION:
drive_process_irp_query_volume_information(disk, irp);
drive_process_irp_query_volume_information(drive, irp);
break;
case IRP_MJ_LOCK_CONTROL :
DEBUG_WARN("MajorFunction IRP_MJ_LOCK_CONTROL silent ignored");
drive_process_irp_silent_ignore(disk, irp);
case IRP_MJ_LOCK_CONTROL:
drive_process_irp_silent_ignore(drive, irp);
break;
case IRP_MJ_DIRECTORY_CONTROL:
drive_process_irp_directory_control(disk, irp);
drive_process_irp_directory_control(drive, irp);
break;
case IRP_MJ_DEVICE_CONTROL:
drive_process_irp_device_control(disk, irp);
drive_process_irp_device_control(drive, irp);
break;
default:
DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
irp->IoStatus = STATUS_NOT_SUPPORTED;
irp->Complete(irp);
break;
}
}
static void drive_process_irp_list(DRIVE_DEVICE* disk)
{
IRP* irp;
while (1)
{
if (WaitForSingleObject(disk->stopEvent, 0) == WAIT_OBJECT_0)
break;
irp = (IRP*) InterlockedPopEntrySList(disk->pIrpList);
if (irp == NULL)
break;
drive_process_irp(disk, irp);
}
}
static void* drive_thread_func(void* arg)
{
DRIVE_DEVICE* disk = (DRIVE_DEVICE*) arg;
HANDLE hdl[] = {disk->irpEvent, disk->stopEvent};
IRP* irp;
wMessage message;
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg;
while (1)
{
DWORD rc = WaitForMultipleObjects(2, hdl, FALSE, INFINITE);
if (rc == WAIT_OBJECT_0 + 1)
break;
while (1)
{
if (!MessageQueue_Wait(drive->IrpQueue))
break;
ResetEvent(disk->irpEvent);
drive_process_irp_list(disk);
}
ExitThread(0);
if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
break;
return NULL;
if (message.id == WMQ_QUIT)
break;
irp = (IRP*) message.wParam;
if (irp)
drive_process_irp(drive, irp);
}
ExitThread(0);
return NULL;
}
static void drive_irp_request(DEVICE* device, IRP* irp)
{
DRIVE_DEVICE* disk = (DRIVE_DEVICE*) device;
InterlockedPushEntrySList(disk->pIrpList, &(irp->ItemEntry));
SetEvent(disk->irpEvent);
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device;
MessageQueue_Post(drive->IrpQueue, NULL, 0, (void*) irp, NULL);
}
static void drive_free(DEVICE* device)
{
IRP* irp;
DRIVE_FILE* file;
DRIVE_DEVICE* disk = (DRIVE_DEVICE*) device;
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device;
SetEvent(disk->stopEvent);
WaitForSingleObject(disk->thread, INFINITE);
CloseHandle(disk->thread);
CloseHandle(disk->irpEvent);
CloseHandle(disk->stopEvent);
MessageQueue_PostQuit(drive->IrpQueue, 0);
WaitForSingleObject(drive->thread, INFINITE);
while ((irp = (IRP*) InterlockedPopEntrySList(disk->pIrpList)) != NULL)
irp->Discard(irp);
CloseHandle(drive->thread);
_aligned_free(disk->pIrpList);
ListDictionary_Free(drive->files);
while ((file = (DRIVE_FILE*) list_dequeue(disk->files)) != NULL)
drive_file_free(file);
list_free(disk->files);
free(disk);
free(drive);
}
void drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char* name, char* path)
{
int i, length;
DRIVE_DEVICE* disk;
DRIVE_DEVICE* drive;
#ifdef WIN32
/*
@ -704,33 +642,31 @@ void drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
if (name[0] && path[0])
{
disk = (DRIVE_DEVICE*) malloc(sizeof(DRIVE_DEVICE));
ZeroMemory(disk, sizeof(DRIVE_DEVICE));
drive = (DRIVE_DEVICE*) malloc(sizeof(DRIVE_DEVICE));
ZeroMemory(drive, sizeof(DRIVE_DEVICE));
disk->device.type = RDPDR_DTYP_FILESYSTEM;
disk->device.name = name;
disk->device.IRPRequest = drive_irp_request;
disk->device.Free = drive_free;
drive->device.type = RDPDR_DTYP_FILESYSTEM;
drive->device.name = name;
drive->device.IRPRequest = drive_irp_request;
drive->device.Free = drive_free;
length = strlen(name);
disk->device.data = Stream_New(NULL, length + 1);
drive->device.data = Stream_New(NULL, length + 1);
for (i = 0; i <= length; i++)
Stream_Write_UINT8(disk->device.data, name[i] < 0 ? '_' : name[i]);
Stream_Write_UINT8(drive->device.data, name[i] < 0 ? '_' : name[i]);
disk->path = path;
disk->files = list_new();
drive->path = path;
disk->pIrpList = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
InitializeSListHead(disk->pIrpList);
drive->files = ListDictionary_New(TRUE);
ListDictionary_Object(drive->files)->fnObjectFree = (OBJECT_FREE_FN) drive_file_free;
disk->irpEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
disk->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
disk->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_thread_func, disk, CREATE_SUSPENDED, NULL);
drive->IrpQueue = MessageQueue_New();
drive->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_thread_func, drive, CREATE_SUSPENDED, NULL);
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) disk);
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) drive);
ResumeThread(disk->thread);
ResumeThread(drive->thread);
}
}

View File

@ -34,9 +34,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -36,8 +36,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -56,8 +56,6 @@ endif()
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -36,5 +36,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -38,10 +38,18 @@
#include "rail_orders.h"
#include "rail_main.h"
void rail_send_channel_data(void* rail_object, void* data, size_t length)
RailClientContext* rail_get_client_interface(void* railObject)
{
RailClientContext* pInterface;
rdpSvcPlugin* plugin = (rdpSvcPlugin*) railObject;
pInterface = (RailClientContext*) *(plugin->channel_entry_points.ppInterface);
return pInterface;
}
void rail_send_channel_data(void* railObject, void* data, size_t length)
{
wStream* s = NULL;
railPlugin* plugin = (railPlugin*) rail_object;
railPlugin* plugin = (railPlugin*) railObject;
s = Stream_New(NULL, length);
Stream_Write(s, data, length);
@ -54,17 +62,17 @@ static void on_free_rail_channel_event(wMessage* event)
rail_free_cloned_order(GetMessageType(event->id), event->wParam);
}
void rail_send_channel_event(void* rail_object, UINT16 event_type, void* param)
void rail_send_channel_event(void* railObject, UINT16 eventType, void* param)
{
void * payload = NULL;
void* payload = NULL;
wMessage* out_event = NULL;
railPlugin* plugin = (railPlugin*) rail_object;
railPlugin* plugin = (railPlugin*) railObject;
payload = rail_clone_order(event_type, param);
payload = rail_clone_order(eventType, param);
if (payload != NULL)
if (payload)
{
out_event = freerdp_event_new(RailChannel_Class, event_type,
out_event = freerdp_event_new(RailChannel_Class, eventType,
on_free_rail_channel_event, payload);
svc_plugin_send_event((rdpSvcPlugin*) plugin, out_event);
@ -78,21 +86,25 @@ static void rail_process_connect(rdpSvcPlugin* plugin)
rail->rail_order = rail_order_new();
rail->rail_order->settings = (rdpSettings*) plugin->channel_entry_points.pExtendedData;
rail->rail_order->plugin = rail;
WLog_Print(rail->log, WLOG_DEBUG, "Connect");
}
static void rail_process_terminate(rdpSvcPlugin* plugin)
{
railPlugin* rail = (railPlugin*) plugin;
WLog_Print(rail->log, WLOG_DEBUG, "Terminate");
}
static void rail_process_receive(rdpSvcPlugin* plugin, wStream* s)
{
railPlugin* rail = (railPlugin*) plugin;
rail_order_recv(rail->rail_order, s);
rail_order_recv(rail, s);
Stream_Free(s, TRUE);
}
static void rail_process_addin_args(rdpRailOrder* rail_order, rdpSettings* settings)
static void rail_process_addin_args(rdpRailOrder* railOrder, rdpSettings* settings)
{
char* exeOrFile;
@ -101,35 +113,35 @@ static void rail_process_addin_args(rdpRailOrder* rail_order, rdpSettings* setti
if (strlen(exeOrFile) >= 2)
{
if (strncmp(exeOrFile, "||", 2) != 0)
rail_order->exec.flags |= RAIL_EXEC_FLAG_FILE;
railOrder->exec.flags |= RAIL_EXEC_FLAG_FILE;
}
rail_string_to_unicode_string(settings->RemoteApplicationProgram, &rail_order->exec.exeOrFile);
rail_string_to_unicode_string(settings->ShellWorkingDirectory, &rail_order->exec.workingDir);
rail_string_to_unicode_string(settings->RemoteApplicationCmdLine, &rail_order->exec.arguments);
rail_string_to_unicode_string(settings->RemoteApplicationProgram, &railOrder->exec.exeOrFile);
rail_string_to_unicode_string(settings->ShellWorkingDirectory, &railOrder->exec.workingDir);
rail_string_to_unicode_string(settings->RemoteApplicationCmdLine, &railOrder->exec.arguments);
rail_send_client_exec_order(rail_order);
rail_send_client_exec_order((railPlugin*) railOrder->plugin, &railOrder->exec);
}
static void rail_recv_set_sysparams_event(rdpRailOrder* rail_order, wMessage* event)
static void rail_recv_set_sysparams_event(rdpRailOrder* railOrder, wMessage* event)
{
RAIL_SYSPARAM_ORDER* sysparam;
/* Send System Parameters */
sysparam = (RAIL_SYSPARAM_ORDER*) event->wParam;
memmove(&rail_order->sysparam, sysparam, sizeof(RAIL_SYSPARAM_ORDER));
memmove(&railOrder->sysparam, sysparam, sizeof(RAIL_SYSPARAM_ORDER));
rail_send_client_sysparams_order(rail_order);
rail_send_client_sysparams_order((railPlugin*) railOrder->plugin, &railOrder->sysparam);
/* execute */
rail_order->exec.flags = RAIL_EXEC_FLAG_EXPAND_ARGUMENTS;
railOrder->exec.flags = RAIL_EXEC_FLAG_EXPAND_ARGUMENTS;
rail_process_addin_args(rail_order, rail_order->settings);
rail_process_addin_args(railOrder, railOrder->settings);
}
static void rail_recv_exec_remote_app_event(rdpRailOrder* rail_order, wMessage* event)
static void rail_recv_exec_remote_app_event(rdpRailOrder* railOrder, wMessage* event)
{
/**
* TODO: replace event system by an API to allow the execution
@ -137,63 +149,62 @@ static void rail_recv_exec_remote_app_event(rdpRailOrder* rail_order, wMessage*
* always built-in, so clients can safely link to it.
*/
//rail_process_addin_args(rail_order, data);
//rail_process_addin_args((railPlugin*) railOrder->plugin, data);
}
static void rail_recv_activate_event(rdpRailOrder* rail_order, wMessage* event)
static void rail_recv_activate_event(rdpRailOrder* railOrder, wMessage* event)
{
RAIL_ACTIVATE_ORDER* activate = (RAIL_ACTIVATE_ORDER*) event->wParam;
CopyMemory(&rail_order->activate, activate, sizeof(RAIL_ACTIVATE_ORDER));
rail_send_client_activate_order(rail_order);
CopyMemory(&railOrder->activate, activate, sizeof(RAIL_ACTIVATE_ORDER));
rail_send_client_activate_order((railPlugin*) railOrder->plugin, &railOrder->activate);
}
static void rail_recv_sysmenu_event(rdpRailOrder* rail_order, wMessage* event)
static void rail_recv_sysmenu_event(rdpRailOrder* railOrder, wMessage* event)
{
RAIL_SYSMENU_ORDER* sysmenu = (RAIL_SYSMENU_ORDER*) event->wParam;
CopyMemory(&rail_order->sysmenu, sysmenu, sizeof(RAIL_SYSMENU_ORDER));
rail_send_client_sysmenu_order(rail_order);
CopyMemory(&railOrder->sysmenu, sysmenu, sizeof(RAIL_SYSMENU_ORDER));
rail_send_client_sysmenu_order((railPlugin*) railOrder->plugin, &railOrder->sysmenu);
}
static void rail_recv_syscommand_event(rdpRailOrder* rail_order, wMessage* event)
static void rail_recv_syscommand_event(rdpRailOrder* railOrder, wMessage* event)
{
RAIL_SYSCOMMAND_ORDER* syscommand = (RAIL_SYSCOMMAND_ORDER*) event->wParam;
CopyMemory(&rail_order->syscommand, syscommand, sizeof(RAIL_SYSCOMMAND_ORDER));
rail_send_client_syscommand_order(rail_order);
CopyMemory(&railOrder->syscommand, syscommand, sizeof(RAIL_SYSCOMMAND_ORDER));
rail_send_client_syscommand_order((railPlugin*) railOrder->plugin, &railOrder->syscommand);
}
static void rail_recv_notify_event(rdpRailOrder* rail_order, wMessage* event)
static void rail_recv_notify_event(rdpRailOrder* railOrder, wMessage* event)
{
RAIL_NOTIFY_EVENT_ORDER* notify = (RAIL_NOTIFY_EVENT_ORDER*) event->wParam;
CopyMemory(&rail_order->notify_event, notify, sizeof(RAIL_NOTIFY_EVENT_ORDER));
rail_send_client_notify_event_order(rail_order);
CopyMemory(&railOrder->notify_event, notify, sizeof(RAIL_NOTIFY_EVENT_ORDER));
rail_send_client_notify_event_order((railPlugin*) railOrder->plugin, &railOrder->notify_event);
}
static void rail_recv_window_move_event(rdpRailOrder* rail_order, wMessage* event)
static void rail_recv_window_move_event(rdpRailOrder* railOrder, wMessage* event)
{
RAIL_WINDOW_MOVE_ORDER* window_move = (RAIL_WINDOW_MOVE_ORDER*) event->wParam;
CopyMemory(&rail_order->window_move, window_move, sizeof(RAIL_WINDOW_MOVE_ORDER));
rail_send_client_window_move_order(rail_order);
CopyMemory(&railOrder->window_move, window_move, sizeof(RAIL_WINDOW_MOVE_ORDER));
rail_send_client_window_move_order((railPlugin*) railOrder->plugin, &railOrder->window_move);
}
static void rail_recv_app_req_event(rdpRailOrder* rail_order, wMessage* event)
static void rail_recv_app_req_event(rdpRailOrder* railOrder, wMessage* event)
{
RAIL_GET_APPID_REQ_ORDER* get_appid_req = (RAIL_GET_APPID_REQ_ORDER*) event->wParam;
CopyMemory(&rail_order->get_appid_req, get_appid_req, sizeof(RAIL_GET_APPID_REQ_ORDER));
rail_send_client_get_appid_req_order(rail_order);
CopyMemory(&railOrder->get_appid_req, get_appid_req, sizeof(RAIL_GET_APPID_REQ_ORDER));
rail_send_client_get_appid_req_order((railPlugin*) railOrder->plugin, &railOrder->get_appid_req);
}
static void rail_recv_langbarinfo_event(rdpRailOrder* rail_order, wMessage* event)
static void rail_recv_langbarinfo_event(rdpRailOrder* railOrder, wMessage* event)
{
RAIL_LANGBAR_INFO_ORDER* langbar_info = (RAIL_LANGBAR_INFO_ORDER*) event->wParam;
CopyMemory(&rail_order->langbar_info, langbar_info, sizeof(RAIL_LANGBAR_INFO_ORDER));
rail_send_client_langbar_info_order(rail_order);
CopyMemory(&railOrder->langbar_info, langbar_info, sizeof(RAIL_LANGBAR_INFO_ORDER));
rail_send_client_langbar_info_order((railPlugin*) railOrder->plugin, &railOrder->langbar_info);
}
static void rail_process_event(rdpSvcPlugin* plugin, wMessage* event)
@ -246,12 +257,255 @@ static void rail_process_event(rdpSvcPlugin* plugin, wMessage* event)
freerdp_event_free(event);
}
/**
* Callback Interface
*/
int rail_client_execute(RailClientContext* context, RAIL_EXEC_ORDER* exec)
{
railPlugin* rail = (railPlugin*) context->handle;
char* exeOrFile;
exeOrFile = exec->RemoteApplicationProgram;
if (!exeOrFile)
return -1;
if (strlen(exeOrFile) >= 2)
{
if (strncmp(exeOrFile, "||", 2) != 0)
exec->flags |= RAIL_EXEC_FLAG_FILE;
}
rail_string_to_unicode_string(exec->RemoteApplicationProgram, &exec->exeOrFile); /* RemoteApplicationProgram */
rail_string_to_unicode_string(exec->RemoteApplicationWorkingDir, &exec->workingDir); /* ShellWorkingDirectory */
rail_string_to_unicode_string(exec->RemoteApplicationArguments, &exec->arguments); /* RemoteApplicationCmdLine */
rail_send_client_exec_order(rail, exec);
return 0;
}
int rail_client_activate(RailClientContext* context, RAIL_ACTIVATE_ORDER* activate)
{
railPlugin* rail = (railPlugin*) context->handle;
rail_send_client_activate_order(rail, activate);
return 0;
}
void rail_send_client_sysparam(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam)
{
wStream* s;
int length;
railPlugin* rail = (railPlugin*) context->handle;
length = RAIL_SYSPARAM_ORDER_LENGTH;
switch (sysparam->param)
{
case SPI_SET_DRAG_FULL_WINDOWS:
case SPI_SET_KEYBOARD_CUES:
case SPI_SET_KEYBOARD_PREF:
case SPI_SET_MOUSE_BUTTON_SWAP:
length += 1;
break;
case SPI_SET_WORK_AREA:
case SPI_DISPLAY_CHANGE:
case SPI_TASKBAR_POS:
length += 8;
break;
case SPI_SET_HIGH_CONTRAST:
length += sysparam->highContrast.colorSchemeLength + 10;
break;
}
s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH + 8);
rail_write_client_sysparam_order(s, sysparam);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSPARAM);
Stream_Free(s, TRUE);
}
int rail_client_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam)
{
if (sysparam->params & SPI_MASK_SET_HIGH_CONTRAST)
{
sysparam->param = SPI_SET_HIGH_CONTRAST;
rail_send_client_sysparam(context, sysparam);
}
if (sysparam->params & SPI_MASK_TASKBAR_POS)
{
sysparam->param = SPI_TASKBAR_POS;
rail_send_client_sysparam(context, sysparam);
}
if (sysparam->params & SPI_MASK_SET_MOUSE_BUTTON_SWAP)
{
sysparam->param = SPI_SET_MOUSE_BUTTON_SWAP;
rail_send_client_sysparam(context, sysparam);
}
if (sysparam->params & SPI_MASK_SET_KEYBOARD_PREF)
{
sysparam->param = SPI_SET_KEYBOARD_PREF;
rail_send_client_sysparam(context, sysparam);
}
if (sysparam->params & SPI_MASK_SET_DRAG_FULL_WINDOWS)
{
sysparam->param = SPI_SET_DRAG_FULL_WINDOWS;
rail_send_client_sysparam(context, sysparam);
}
if (sysparam->params & SPI_MASK_SET_KEYBOARD_CUES)
{
sysparam->param = SPI_SET_KEYBOARD_CUES;
rail_send_client_sysparam(context, sysparam);
}
if (sysparam->params & SPI_MASK_SET_WORK_AREA)
{
sysparam->param = SPI_SET_WORK_AREA;
rail_send_client_sysparam(context, sysparam);
}
return 0;
}
int rail_server_system_param(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam)
{
return 0; /* stub - should be registered by client */
}
int rail_client_system_command(RailClientContext* context, RAIL_SYSCOMMAND_ORDER* syscommand)
{
railPlugin* rail = (railPlugin*) context->handle;
rail_send_client_syscommand_order(rail, syscommand);
return 0;
}
int rail_client_handshake(RailClientContext* context, RAIL_HANDSHAKE_ORDER* handshake)
{
railPlugin* rail = (railPlugin*) context->handle;
rail_send_handshake_order(rail, handshake);
return 0;
}
int rail_server_handshake(RailClientContext* context, RAIL_HANDSHAKE_ORDER* handshake)
{
return 0; /* stub - should be registered by client */
}
int rail_client_handshake_ex(RailClientContext* context, RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{
railPlugin* rail = (railPlugin*) context->handle;
rail_send_handshake_ex_order(rail, handshakeEx);
return 0;
}
int rail_server_handshake_ex(RailClientContext* context, RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{
return 0; /* stub - should be registered by client */
}
int rail_client_notify_event(RailClientContext* context, RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
{
railPlugin* rail = (railPlugin*) context->handle;
rail_send_client_notify_event_order(rail, notifyEvent);
return 0;
}
int rail_client_window_move(RailClientContext* context, RAIL_WINDOW_MOVE_ORDER* windowMove)
{
railPlugin* rail = (railPlugin*) context->handle;
rail_send_client_window_move_order(rail, windowMove);
return 0;
}
int rail_server_local_move_size(RailClientContext* context, RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
{
return 0; /* stub - should be registered by client */
}
int rail_server_min_max_info(RailClientContext* context, RAIL_MINMAXINFO_ORDER* minMaxInfo)
{
return 0; /* stub - should be registered by client */
}
int rail_client_information(RailClientContext* context, RAIL_CLIENT_STATUS_ORDER* clientStatus)
{
railPlugin* rail = (railPlugin*) context->handle;
rail_send_client_status_order(rail, clientStatus);
return 0;
}
int rail_client_system_menu(RailClientContext* context, RAIL_SYSMENU_ORDER* sysmenu)
{
railPlugin* rail = (railPlugin*) context->handle;
rail_send_client_sysmenu_order(rail, sysmenu);
return 0;
}
int rail_client_language_bar_info(RailClientContext* context, RAIL_LANGBAR_INFO_ORDER* langBarInfo)
{
railPlugin* rail = (railPlugin*) context->handle;
rail_send_client_langbar_info_order(rail, langBarInfo);
return 0;
}
int rail_server_language_bar_info(RailClientContext* context, RAIL_LANGBAR_INFO_ORDER* langBarInfo)
{
return 0; /* stub - should be registered by client */
}
int rail_server_execute_result(RailClientContext* context, RAIL_EXEC_RESULT_ORDER* execResult)
{
return 0; /* stub - should be registered by client */
}
int rail_client_get_appid_request(RailClientContext* context, RAIL_GET_APPID_REQ_ORDER* getAppIdReq)
{
railPlugin* rail = (railPlugin*) context->handle;
rail_send_client_get_appid_req_order(rail, getAppIdReq);
return 0;
}
int rail_server_get_appid_response(RailClientContext* context, RAIL_GET_APPID_RESP_ORDER* getAppIdResp)
{
return 0; /* stub - should be registered by client */
}
/* rail is always built-in */
#define VirtualChannelEntry rail_VirtualChannelEntry
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
railPlugin* _p;
RailClientContext* context;
CHANNEL_ENTRY_POINTS_EX* pEntryPointsEx;
_p = (railPlugin*) malloc(sizeof(railPlugin));
ZeroMemory(_p, sizeof(railPlugin));
@ -269,6 +523,44 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
_p->plugin.event_callback = rail_process_event;
_p->plugin.terminate_callback = rail_process_terminate;
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_EX*) pEntryPoints;
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_EX)) &&
(pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
{
context = (RailClientContext*) malloc(sizeof(RailClientContext));
context->handle = (void*) _p;
context->ClientExecute = rail_client_execute;
context->ClientActivate = rail_client_activate;
context->ClientSystemParam = rail_client_system_param;
context->ServerSystemParam = rail_server_system_param;
context->ClientSystemCommand = rail_client_system_command;
context->ClientHandshake = rail_client_handshake;
context->ServerHandshake = rail_server_handshake;
context->ClientHandshakeEx = rail_client_handshake_ex;
context->ServerHandshakeEx = rail_server_handshake_ex;
context->ClientNotifyEvent = rail_client_notify_event;
context->ClientWindowMove = rail_client_window_move;
context->ServerLocalMoveSize = rail_server_local_move_size;
context->ServerMinMaxInfo = rail_server_min_max_info;
context->ClientInformation = rail_client_information;
context->ClientSystemMenu = rail_client_system_menu;
context->ClientLanguageBarInfo = rail_client_language_bar_info;
context->ServerLanguageBarInfo = rail_server_language_bar_info;
context->ServerExecuteResult = rail_server_execute_result;
context->ClientGetAppIdRequest = rail_client_get_appid_request;
context->ServerGetAppIdResponse = rail_server_get_appid_response;
*(pEntryPointsEx->ppInterface) = (void*) context;
}
WLog_Init();
_p->log = WLog_Get("com.freerdp.channels.rail.client");
WLog_Print(_p->log, WLOG_DEBUG, "VirtualChannelEntry");
svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints);
return 1;

View File

@ -24,9 +24,12 @@
#include <freerdp/rail.h>
#include <freerdp/settings.h>
#include <freerdp/utils/debug.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/rail.h>
#include <winpr/crt.h>
#include <winpr/wlog.h>
#include <winpr/stream.h>
#include "../rail_common.h"
@ -34,13 +37,15 @@
struct rail_plugin
{
rdpSvcPlugin plugin;
wLog* log;
rdpRailOrder* rail_order;
};
typedef struct rail_plugin railPlugin;
RailClientContext* rail_get_client_interface(void* railObject);
void rail_send_channel_event(void* rail_object, UINT16 event_type, void* param);
void rail_send_channel_data(void* rail_object, void* data, size_t length);
#endif /* FREERDP_CHANNEL_CLIENT_RAIL_MAIN_H */

View File

@ -31,9 +31,7 @@
#include "rail_orders.h"
void rail_send_pdu(rdpRailOrder* rail_order, wStream* s, UINT16 orderType)
void rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType)
{
UINT16 orderLength;
@ -43,30 +41,31 @@ void rail_send_pdu(rdpRailOrder* rail_order, wStream* s, UINT16 orderType)
rail_write_pdu_header(s, orderType, orderLength);
Stream_SetPosition(s, orderLength);
/* send */
DEBUG_RAIL("Sending %s PDU, length:%d",
WLog_Print(rail->log, WLOG_DEBUG, "Sending %s PDU, length: %d",
RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength);
rail_send_channel_data(rail_order->plugin, Stream_Buffer(s), orderLength);
rail_send_channel_data(rail, Stream_Buffer(s), orderLength);
}
void rail_write_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* high_contrast)
void rail_write_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* highContrast)
{
high_contrast->colorSchemeLength = high_contrast->colorScheme.length + 2;
Stream_Write_UINT32(s, high_contrast->flags); /* flags (4 bytes) */
Stream_Write_UINT32(s, high_contrast->colorSchemeLength); /* colorSchemeLength (4 bytes) */
rail_write_unicode_string(s, &high_contrast->colorScheme); /* colorScheme */
highContrast->colorSchemeLength = highContrast->colorScheme.length + 2;
Stream_Write_UINT32(s, highContrast->flags); /* flags (4 bytes) */
Stream_Write_UINT32(s, highContrast->colorSchemeLength); /* colorSchemeLength (4 bytes) */
rail_write_unicode_string(s, &highContrast->colorScheme); /* colorScheme */
}
BOOL rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* exec_result)
BOOL rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDER* execResult)
{
if (Stream_GetRemainingLength(s) < 8)
return FALSE;
Stream_Read_UINT16(s, exec_result->flags); /* flags (2 bytes) */
Stream_Read_UINT16(s, exec_result->execResult); /* execResult (2 bytes) */
Stream_Read_UINT32(s, exec_result->rawResult); /* rawResult (4 bytes) */
Stream_Read_UINT16(s, execResult->flags); /* flags (2 bytes) */
Stream_Read_UINT16(s, execResult->execResult); /* execResult (2 bytes) */
Stream_Read_UINT32(s, execResult->rawResult); /* rawResult (4 bytes) */
Stream_Seek_UINT16(s); /* padding (2 bytes) */
return rail_read_unicode_string(s, &exec_result->exeOrFile); /* exeOrFile */
return rail_read_unicode_string(s, &execResult->exeOrFile); /* exeOrFile */
}
BOOL rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam)
@ -75,6 +74,7 @@ BOOL rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam)
if (Stream_GetRemainingLength(s) < 5)
return FALSE;
Stream_Read_UINT32(s, sysparam->param); /* systemParam (4 bytes) */
Stream_Read_UINT8(s, body); /* body (1 byte) */
@ -91,6 +91,7 @@ BOOL rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam)
default:
break;
}
return TRUE;
}
@ -98,6 +99,7 @@ BOOL rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmax
{
if (Stream_GetRemainingLength(s) < 20)
return FALSE;
Stream_Read_UINT32(s, minmaxinfo->windowId); /* windowId (4 bytes) */
Stream_Read_UINT16(s, minmaxinfo->maxWidth); /* maxWidth (2 bytes) */
Stream_Read_UINT16(s, minmaxinfo->maxHeight); /* maxHeight (2 bytes) */
@ -107,49 +109,53 @@ BOOL rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* minmax
Stream_Read_UINT16(s, minmaxinfo->minTrackHeight); /* minTrackHeight (2 bytes) */
Stream_Read_UINT16(s, minmaxinfo->maxTrackWidth); /* maxTrackWidth (2 bytes) */
Stream_Read_UINT16(s, minmaxinfo->maxTrackHeight); /* maxTrackHeight (2 bytes) */
return TRUE;
}
BOOL rail_read_server_localmovesize_order(wStream* s, RAIL_LOCALMOVESIZE_ORDER* localmovesize)
BOOL rail_read_server_localmovesize_order(wStream* s, RAIL_LOCALMOVESIZE_ORDER* localMoveSize)
{
UINT16 isMoveSizeStart;
if (Stream_GetRemainingLength(s) < 12)
return FALSE;
Stream_Read_UINT32(s, localmovesize->windowId); /* windowId (4 bytes) */
Stream_Read_UINT32(s, localMoveSize->windowId); /* windowId (4 bytes) */
Stream_Read_UINT16(s, isMoveSizeStart); /* isMoveSizeStart (2 bytes) */
localmovesize->isMoveSizeStart = (isMoveSizeStart != 0) ? TRUE : FALSE;
localMoveSize->isMoveSizeStart = (isMoveSizeStart != 0) ? TRUE : FALSE;
Stream_Read_UINT16(s, localMoveSize->moveSizeType); /* moveSizeType (2 bytes) */
Stream_Read_UINT16(s, localMoveSize->posX); /* posX (2 bytes) */
Stream_Read_UINT16(s, localMoveSize->posY); /* posY (2 bytes) */
Stream_Read_UINT16(s, localmovesize->moveSizeType); /* moveSizeType (2 bytes) */
Stream_Read_UINT16(s, localmovesize->posX); /* posX (2 bytes) */
Stream_Read_UINT16(s, localmovesize->posY); /* posY (2 bytes) */
return TRUE;
}
BOOL rail_read_server_get_appid_resp_order(wStream* s, RAIL_GET_APPID_RESP_ORDER* get_appid_resp)
BOOL rail_read_server_get_appid_resp_order(wStream* s, RAIL_GET_APPID_RESP_ORDER* getAppidResp)
{
if (Stream_GetRemainingLength(s) < 516)
return FALSE;
Stream_Read_UINT32(s, get_appid_resp->windowId); /* windowId (4 bytes) */
Stream_Read(s, &get_appid_resp->applicationIdBuffer[0], 512); /* applicationId (256 UNICODE chars) */
get_appid_resp->applicationId.length = 512;
get_appid_resp->applicationId.string = &get_appid_resp->applicationIdBuffer[0];
Stream_Read_UINT32(s, getAppidResp->windowId); /* windowId (4 bytes) */
Stream_Read(s, (BYTE*) &(getAppidResp->applicationId), 512); /* applicationId (256 UNICODE chars) */
return TRUE;
}
BOOL rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbar_info)
BOOL rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo)
{
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
Stream_Read_UINT32(s, langbar_info->languageBarStatus); /* languageBarStatus (4 bytes) */
Stream_Read_UINT32(s, langbarInfo->languageBarStatus); /* languageBarStatus (4 bytes) */
return TRUE;
}
void rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* client_status)
void rail_write_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* clientStatus)
{
Stream_Write_UINT32(s, client_status->flags); /* flags (4 bytes) */
Stream_Write_UINT32(s, clientStatus->flags); /* flags (4 bytes) */
}
void rail_write_client_exec_order(wStream* s, RAIL_EXEC_ORDER* exec)
@ -166,6 +172,7 @@ void rail_write_client_exec_order(wStream* s, RAIL_EXEC_ORDER* exec)
void rail_write_client_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam)
{
BYTE body;
Stream_Write_UINT32(s, sysparam->param); /* systemParam (4 bytes) */
switch (sysparam->param)
@ -240,143 +247,220 @@ void rail_write_client_syscommand_order(wStream* s, RAIL_SYSCOMMAND_ORDER* sysco
Stream_Write_UINT16(s, syscommand->command); /* command (2 bytes) */
}
void rail_write_client_notify_event_order(wStream* s, RAIL_NOTIFY_EVENT_ORDER* notify_event)
void rail_write_client_notify_event_order(wStream* s, RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
{
Stream_Write_UINT32(s, notify_event->windowId); /* windowId (4 bytes) */
Stream_Write_UINT32(s, notify_event->notifyIconId); /* notifyIconId (4 bytes) */
Stream_Write_UINT32(s, notify_event->message); /* notifyIconId (4 bytes) */
Stream_Write_UINT32(s, notifyEvent->windowId); /* windowId (4 bytes) */
Stream_Write_UINT32(s, notifyEvent->notifyIconId); /* notifyIconId (4 bytes) */
Stream_Write_UINT32(s, notifyEvent->message); /* notifyIconId (4 bytes) */
}
void rail_write_client_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* window_move)
void rail_write_client_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* windowMove)
{
Stream_Write_UINT32(s, window_move->windowId); /* windowId (4 bytes) */
Stream_Write_UINT16(s, window_move->left); /* left (2 bytes) */
Stream_Write_UINT16(s, window_move->top); /* top (2 bytes) */
Stream_Write_UINT16(s, window_move->right); /* right (2 bytes) */
Stream_Write_UINT16(s, window_move->bottom); /* bottom (2 bytes) */
Stream_Write_UINT32(s, windowMove->windowId); /* windowId (4 bytes) */
Stream_Write_UINT16(s, windowMove->left); /* left (2 bytes) */
Stream_Write_UINT16(s, windowMove->top); /* top (2 bytes) */
Stream_Write_UINT16(s, windowMove->right); /* right (2 bytes) */
Stream_Write_UINT16(s, windowMove->bottom); /* bottom (2 bytes) */
}
void rail_write_client_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* get_appid_req)
void rail_write_client_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* getAppidReq)
{
Stream_Write_UINT32(s, get_appid_req->windowId); /* windowId (4 bytes) */
Stream_Write_UINT32(s, getAppidReq->windowId); /* windowId (4 bytes) */
}
void rail_write_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbar_info)
void rail_write_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo)
{
Stream_Write_UINT32(s, langbar_info->languageBarStatus); /* languageBarStatus (4 bytes) */
Stream_Write_UINT32(s, langbarInfo->languageBarStatus); /* languageBarStatus (4 bytes) */
}
BOOL rail_recv_handshake_order(rdpRailOrder* rail_order, wStream* s)
BOOL rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake, wStream* s)
{
if (!rail_read_handshake_order(s, &rail_order->handshake))
RAIL_SYSPARAM_ORDER sysparam;
RAIL_CLIENT_STATUS_ORDER clientStatus;
RailClientContext* context = rail_get_client_interface(rail);
if (!rail_read_handshake_order(s, handshake))
return FALSE;
rail_order->handshake.buildNumber = 0x00001DB0;
rail_send_handshake_order(rail_order);
if (context->custom)
{
IFCALL(context->ServerHandshake, context, handshake);
return TRUE;
}
rail_order->client_status.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE;
rail_send_client_status_order(rail_order);
handshake->buildNumber = 0x00001DB0;
rail_send_handshake_order(rail, handshake);
ZeroMemory(&clientStatus, sizeof(RAIL_CLIENT_STATUS_ORDER));
clientStatus.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE;
rail_send_client_status_order(rail, &clientStatus);
/* sysparam update */
rail_order->sysparam.params = 0;
ZeroMemory(&sysparam, sizeof(RAIL_SYSPARAM_ORDER));
rail_order->sysparam.params |= SPI_MASK_SET_HIGH_CONTRAST;
rail_order->sysparam.highContrast.colorScheme.string = NULL;
rail_order->sysparam.highContrast.colorScheme.length = 0;
rail_order->sysparam.highContrast.flags = 0x7E;
sysparam.params = 0;
rail_order->sysparam.params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP;
rail_order->sysparam.mouseButtonSwap = FALSE;
sysparam.params |= SPI_MASK_SET_HIGH_CONTRAST;
sysparam.highContrast.colorScheme.string = NULL;
sysparam.highContrast.colorScheme.length = 0;
sysparam.highContrast.flags = 0x7E;
rail_order->sysparam.params |= SPI_MASK_SET_KEYBOARD_PREF;
rail_order->sysparam.keyboardPref = FALSE;
sysparam.params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP;
sysparam.mouseButtonSwap = FALSE;
rail_order->sysparam.params |= SPI_MASK_SET_DRAG_FULL_WINDOWS;
rail_order->sysparam.dragFullWindows = FALSE;
sysparam.params |= SPI_MASK_SET_KEYBOARD_PREF;
sysparam.keyboardPref = FALSE;
rail_order->sysparam.params |= SPI_MASK_SET_KEYBOARD_CUES;
rail_order->sysparam.keyboardCues = FALSE;
sysparam.params |= SPI_MASK_SET_DRAG_FULL_WINDOWS;
sysparam.dragFullWindows = FALSE;
rail_order->sysparam.params |= SPI_MASK_SET_WORK_AREA;
rail_order->sysparam.workArea.left = 0;
rail_order->sysparam.workArea.top = 0;
rail_order->sysparam.workArea.right = 1024;
rail_order->sysparam.workArea.bottom = 768;
sysparam.params |= SPI_MASK_SET_KEYBOARD_CUES;
sysparam.keyboardCues = FALSE;
rail_send_channel_event(rail_order->plugin,
RailChannel_GetSystemParam, &rail_order->sysparam);
sysparam.params |= SPI_MASK_SET_WORK_AREA;
sysparam.workArea.left = 0;
sysparam.workArea.top = 0;
sysparam.workArea.right = 1024;
sysparam.workArea.bottom = 768;
rail_send_channel_event(rail, RailChannel_GetSystemParam, &sysparam);
return TRUE;
}
BOOL rail_recv_exec_result_order(rdpRailOrder* rail_order, wStream* s)
BOOL rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* handshakeEx, wStream* s)
{
if (!rail_read_server_exec_result_order(s, &rail_order->exec_result))
RailClientContext* context = rail_get_client_interface(rail);
if (!rail_read_handshake_ex_order(s, handshakeEx))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RailChannel_ServerExecuteResult, &rail_order->exec_result);
if (context->custom)
{
IFCALL(context->ClientHandshakeEx, context, handshakeEx);
}
return TRUE;
}
BOOL rail_recv_server_sysparam_order(rdpRailOrder* rail_order, wStream* s)
BOOL rail_recv_exec_result_order(railPlugin* rail, RAIL_EXEC_RESULT_ORDER* execResult, wStream* s)
{
if (!rail_read_server_sysparam_order(s, &rail_order->sysparam))
RailClientContext* context = rail_get_client_interface(rail);
ZeroMemory(execResult, sizeof(RAIL_EXEC_RESULT_ORDER));
if (!rail_read_server_exec_result_order(s, execResult))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RailChannel_ServerSystemParam, &rail_order->sysparam);
if (context->custom)
{
IFCALL(context->ServerExecuteResult, context, execResult);
}
else
{
rail_send_channel_event(rail, RailChannel_ServerExecuteResult, execResult);
}
return TRUE;
}
BOOL rail_recv_server_minmaxinfo_order(rdpRailOrder* rail_order, wStream* s)
BOOL rail_recv_server_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam, wStream* s)
{
if (!rail_read_server_minmaxinfo_order(s, &rail_order->minmaxinfo))
RailClientContext* context = rail_get_client_interface(rail);
if (!rail_read_server_sysparam_order(s, sysparam))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RailChannel_ServerMinMaxInfo, &rail_order->minmaxinfo);
if (context->custom)
{
IFCALL(context->ServerSystemParam, context, sysparam);
}
else
{
rail_send_channel_event(rail, RailChannel_ServerSystemParam, sysparam);
}
return TRUE;
}
BOOL rail_recv_server_localmovesize_order(rdpRailOrder* rail_order, wStream* s)
BOOL rail_recv_server_minmaxinfo_order(railPlugin* rail, RAIL_MINMAXINFO_ORDER* minMaxInfo, wStream* s)
{
if (!rail_read_server_localmovesize_order(s, &rail_order->localmovesize))
RailClientContext* context = rail_get_client_interface(rail);
if (!rail_read_server_minmaxinfo_order(s, minMaxInfo))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RailChannel_ServerLocalMoveSize, &rail_order->localmovesize);
if (context->custom)
{
IFCALL(context->ServerMinMaxInfo, context, minMaxInfo);
}
else
{
rail_send_channel_event(rail, RailChannel_ServerMinMaxInfo, minMaxInfo);
}
return TRUE;
}
BOOL rail_recv_server_get_appid_resp_order(rdpRailOrder* rail_order, wStream* s)
BOOL rail_recv_server_localmovesize_order(railPlugin* rail, RAIL_LOCALMOVESIZE_ORDER* localMoveSize, wStream* s)
{
if (!rail_read_server_get_appid_resp_order(s, &rail_order->get_appid_resp))
RailClientContext* context = rail_get_client_interface(rail);
if (!rail_read_server_localmovesize_order(s, localMoveSize))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RailChannel_ServerGetAppIdResponse, &rail_order->get_appid_resp);
if (context->custom)
{
IFCALL(context->ServerLocalMoveSize, context, localMoveSize);
}
else
{
rail_send_channel_event(rail, RailChannel_ServerLocalMoveSize, localMoveSize);
}
return TRUE;
}
BOOL rail_recv_langbar_info_order(rdpRailOrder* rail_order, wStream* s)
BOOL rail_recv_server_get_appid_resp_order(railPlugin* rail, RAIL_GET_APPID_RESP_ORDER* getAppIdResp, wStream* s)
{
if (!rail_read_langbar_info_order(s, &rail_order->langbar_info))
RailClientContext* context = rail_get_client_interface(rail);
if (!rail_read_server_get_appid_resp_order(s, getAppIdResp))
return FALSE;
rail_send_channel_event(rail_order->plugin,
RailChannel_ServerLanguageBarInfo, &rail_order->langbar_info);
if (context->custom)
{
IFCALL(context->ServerGetAppIdResponse, context, getAppIdResp);
}
else
{
rail_send_channel_event(rail, RailChannel_ServerGetAppIdResponse, getAppIdResp);
}
return TRUE;
}
BOOL rail_order_recv(rdpRailOrder* rail_order, wStream* s)
BOOL rail_recv_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORDER* langBarInfo, wStream* s)
{
RailClientContext* context = rail_get_client_interface(rail);
if (!rail_read_langbar_info_order(s, langBarInfo))
return FALSE;
if (context->custom)
{
IFCALL(context->ServerLanguageBarInfo, context, langBarInfo);
}
else
{
rail_send_channel_event(rail, RailChannel_ServerLanguageBarInfo, langBarInfo);
}
return TRUE;
}
BOOL rail_order_recv(railPlugin* rail, wStream* s)
{
UINT16 orderType;
UINT16 orderLength;
@ -384,81 +468,118 @@ BOOL rail_order_recv(rdpRailOrder* rail_order, wStream* s)
if (!rail_read_pdu_header(s, &orderType, &orderLength))
return FALSE;
DEBUG_RAIL("Received %s PDU, length:%d",
WLog_Print(rail->log, WLOG_DEBUG, "Received %s PDU, length: %d",
RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength);
switch (orderType)
{
case RDP_RAIL_ORDER_HANDSHAKE:
return rail_recv_handshake_order(rail_order, s);
{
RAIL_HANDSHAKE_ORDER handshake;
return rail_recv_handshake_order(rail, &handshake, s);
}
case RDP_RAIL_ORDER_HANDSHAKE_EX:
{
RAIL_HANDSHAKE_EX_ORDER handshakeEx;
return rail_recv_handshake_ex_order(rail, &handshakeEx, s);
}
case RDP_RAIL_ORDER_EXEC_RESULT:
return rail_recv_exec_result_order(rail_order, s);
{
RAIL_EXEC_RESULT_ORDER execResult;
return rail_recv_exec_result_order(rail, &execResult, s);
}
case RDP_RAIL_ORDER_SYSPARAM:
return rail_recv_server_sysparam_order(rail_order, s);
{
RAIL_SYSPARAM_ORDER sysparam;
return rail_recv_server_sysparam_order(rail, &sysparam, s);
}
case RDP_RAIL_ORDER_MINMAXINFO:
return rail_recv_server_minmaxinfo_order(rail_order, s);
{
RAIL_MINMAXINFO_ORDER minMaxInfo;
return rail_recv_server_minmaxinfo_order(rail, &minMaxInfo, s);
}
case RDP_RAIL_ORDER_LOCALMOVESIZE:
return rail_recv_server_localmovesize_order(rail_order, s);
{
RAIL_LOCALMOVESIZE_ORDER localMoveSize;
return rail_recv_server_localmovesize_order(rail, &localMoveSize, s);
}
case RDP_RAIL_ORDER_GET_APPID_RESP:
return rail_recv_server_get_appid_resp_order(rail_order, s);
{
RAIL_GET_APPID_RESP_ORDER getAppIdResp;
return rail_recv_server_get_appid_resp_order(rail, &getAppIdResp, s);
}
case RDP_RAIL_ORDER_LANGBARINFO:
return rail_recv_langbar_info_order(rail_order, s);
{
RAIL_LANGBAR_INFO_ORDER langBarInfo;
return rail_recv_langbar_info_order(rail, &langBarInfo, s);
}
default:
fprintf(stderr, "Unknown RAIL PDU order reveived.");
break;
}
return TRUE;
}
void rail_send_handshake_order(rdpRailOrder* rail_order)
void rail_send_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake)
{
wStream* s;
s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
rail_write_handshake_order(s, &rail_order->handshake);
rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_HANDSHAKE);
rail_write_handshake_order(s, handshake);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_HANDSHAKE);
Stream_Free(s, TRUE);
}
void rail_send_client_status_order(rdpRailOrder* rail_order)
void rail_send_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{
wStream* s;
s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
rail_write_handshake_ex_order(s, handshakeEx);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_HANDSHAKE_EX);
Stream_Free(s, TRUE);
}
void rail_send_client_status_order(railPlugin* rail, RAIL_CLIENT_STATUS_ORDER* clientStatus)
{
wStream* s;
s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH);
rail_write_client_status_order(s, &rail_order->client_status);
rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_CLIENTSTATUS);
rail_write_client_status_order(s, clientStatus);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_CLIENTSTATUS);
Stream_Free(s, TRUE);
}
void rail_send_client_exec_order(rdpRailOrder* rail_order)
void rail_send_client_exec_order(railPlugin* rail, RAIL_EXEC_ORDER* exec)
{
wStream* s;
int length;
length = RAIL_EXEC_ORDER_LENGTH +
rail_order->exec.exeOrFile.length +
rail_order->exec.workingDir.length +
rail_order->exec.arguments.length;
exec->exeOrFile.length +
exec->workingDir.length +
exec->arguments.length;
s = rail_pdu_init(RAIL_EXEC_ORDER_LENGTH);
rail_write_client_exec_order(s, &rail_order->exec);
rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_EXEC);
rail_write_client_exec_order(s, exec);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_EXEC);
Stream_Free(s, TRUE);
}
void rail_send_client_sysparam_order(rdpRailOrder* rail_order)
void rail_send_client_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam)
{
wStream* s;
int length;
length = RAIL_SYSPARAM_ORDER_LENGTH;
switch (rail_order->sysparam.param)
switch (sysparam->param)
{
case SPI_SET_DRAG_FULL_WINDOWS:
case SPI_SET_KEYBOARD_CUES:
@ -474,139 +595,142 @@ void rail_send_client_sysparam_order(rdpRailOrder* rail_order)
break;
case SPI_SET_HIGH_CONTRAST:
length += rail_order->sysparam.highContrast.colorSchemeLength + 10;
length += sysparam->highContrast.colorSchemeLength + 10;
break;
}
s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH + 8);
rail_write_client_sysparam_order(s, &rail_order->sysparam);
rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_SYSPARAM);
rail_write_client_sysparam_order(s, sysparam);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSPARAM);
Stream_Free(s, TRUE);
}
void rail_send_client_sysparams_order(rdpRailOrder* rail_order)
void rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam)
{
if (rail_order->sysparam.params & SPI_MASK_SET_HIGH_CONTRAST)
if (sysparam->params & SPI_MASK_SET_HIGH_CONTRAST)
{
rail_order->sysparam.param = SPI_SET_HIGH_CONTRAST;
rail_send_client_sysparam_order(rail_order);
sysparam->param = SPI_SET_HIGH_CONTRAST;
rail_send_client_sysparam_order(rail, sysparam);
}
if (rail_order->sysparam.params & SPI_MASK_TASKBAR_POS)
if (sysparam->params & SPI_MASK_TASKBAR_POS)
{
rail_order->sysparam.param = SPI_TASKBAR_POS;
rail_send_client_sysparam_order(rail_order);
sysparam->param = SPI_TASKBAR_POS;
rail_send_client_sysparam_order(rail, sysparam);
}
if (rail_order->sysparam.params & SPI_MASK_SET_MOUSE_BUTTON_SWAP)
if (sysparam->params & SPI_MASK_SET_MOUSE_BUTTON_SWAP)
{
rail_order->sysparam.param = SPI_SET_MOUSE_BUTTON_SWAP;
rail_send_client_sysparam_order(rail_order);
sysparam->param = SPI_SET_MOUSE_BUTTON_SWAP;
rail_send_client_sysparam_order(rail, sysparam);
}
if (rail_order->sysparam.params & SPI_MASK_SET_KEYBOARD_PREF)
if (sysparam->params & SPI_MASK_SET_KEYBOARD_PREF)
{
rail_order->sysparam.param = SPI_SET_KEYBOARD_PREF;
rail_send_client_sysparam_order(rail_order);
sysparam->param = SPI_SET_KEYBOARD_PREF;
rail_send_client_sysparam_order(rail, sysparam);
}
if (rail_order->sysparam.params & SPI_MASK_SET_DRAG_FULL_WINDOWS)
if (sysparam->params & SPI_MASK_SET_DRAG_FULL_WINDOWS)
{
rail_order->sysparam.param = SPI_SET_DRAG_FULL_WINDOWS;
rail_send_client_sysparam_order(rail_order);
sysparam->param = SPI_SET_DRAG_FULL_WINDOWS;
rail_send_client_sysparam_order(rail, sysparam);
}
if (rail_order->sysparam.params & SPI_MASK_SET_KEYBOARD_CUES)
if (sysparam->params & SPI_MASK_SET_KEYBOARD_CUES)
{
rail_order->sysparam.param = SPI_SET_KEYBOARD_CUES;
rail_send_client_sysparam_order(rail_order);
sysparam->param = SPI_SET_KEYBOARD_CUES;
rail_send_client_sysparam_order(rail, sysparam);
}
if (rail_order->sysparam.params & SPI_MASK_SET_WORK_AREA)
if (sysparam->params & SPI_MASK_SET_WORK_AREA)
{
rail_order->sysparam.param = SPI_SET_WORK_AREA;
rail_send_client_sysparam_order(rail_order);
sysparam->param = SPI_SET_WORK_AREA;
rail_send_client_sysparam_order(rail, sysparam);
}
}
void rail_send_client_activate_order(rdpRailOrder* rail_order)
void rail_send_client_activate_order(railPlugin* rail, RAIL_ACTIVATE_ORDER* activate)
{
wStream* s;
s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH);
rail_write_client_activate_order(s, &rail_order->activate);
rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_ACTIVATE);
rail_write_client_activate_order(s, activate);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_ACTIVATE);
Stream_Free(s, TRUE);
}
void rail_send_client_sysmenu_order(rdpRailOrder* rail_order)
void rail_send_client_sysmenu_order(railPlugin* rail, RAIL_SYSMENU_ORDER* sysmenu)
{
wStream* s;
s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH);
rail_write_client_sysmenu_order(s, &rail_order->sysmenu);
rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_SYSMENU);
rail_write_client_sysmenu_order(s, sysmenu);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSMENU);
Stream_Free(s, TRUE);
}
void rail_send_client_syscommand_order(rdpRailOrder* rail_order)
void rail_send_client_syscommand_order(railPlugin* rail, RAIL_SYSCOMMAND_ORDER* syscommand)
{
wStream* s;
s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH);
rail_write_client_syscommand_order(s, &rail_order->syscommand);
rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_SYSCOMMAND);
rail_write_client_syscommand_order(s, syscommand);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSCOMMAND);
Stream_Free(s, TRUE);
}
void rail_send_client_notify_event_order(rdpRailOrder* rail_order)
void rail_send_client_notify_event_order(railPlugin* rail, RAIL_NOTIFY_EVENT_ORDER* notifyEvent)
{
wStream* s;
s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH);
rail_write_client_notify_event_order(s, &rail_order->notify_event);
rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_NOTIFY_EVENT);
rail_write_client_notify_event_order(s, notifyEvent);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_NOTIFY_EVENT);
Stream_Free(s, TRUE);
}
void rail_send_client_window_move_order(rdpRailOrder* rail_order)
void rail_send_client_window_move_order(railPlugin* rail, RAIL_WINDOW_MOVE_ORDER* windowMove)
{
wStream* s;
s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH);
rail_write_client_window_move_order(s, &rail_order->window_move);
rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_WINDOWMOVE);
rail_write_client_window_move_order(s, windowMove);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_WINDOWMOVE);
Stream_Free(s, TRUE);
}
void rail_send_client_get_appid_req_order(rdpRailOrder* rail_order)
void rail_send_client_get_appid_req_order(railPlugin* rail, RAIL_GET_APPID_REQ_ORDER* getAppIdReq)
{
wStream* s;
s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH);
rail_write_client_get_appid_req_order(s, &rail_order->get_appid_req);
rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_GET_APPID_REQ);
rail_write_client_get_appid_req_order(s, getAppIdReq);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_GET_APPID_REQ);
Stream_Free(s, TRUE);
}
void rail_send_client_langbar_info_order(rdpRailOrder* rail_order)
void rail_send_client_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORDER* langBarInfo)
{
wStream* s;
s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH);
rail_write_langbar_info_order(s, &rail_order->langbar_info);
rail_send_pdu(rail_order, s, RDP_RAIL_ORDER_LANGBARINFO);
rail_write_langbar_info_order(s, langBarInfo);
rail_send_pdu(rail, s, RDP_RAIL_ORDER_LANGBARINFO);
Stream_Free(s, TRUE);
}
rdpRailOrder* rail_order_new()
{
rdpRailOrder* rail_order;
rdpRailOrder* railOrder;
rail_order = (rdpRailOrder*) malloc(sizeof(rdpRailOrder));
ZeroMemory(rail_order, sizeof(rdpRailOrder));
return rail_order;
railOrder = (rdpRailOrder*) malloc(sizeof(rdpRailOrder));
if (railOrder)
{
ZeroMemory(railOrder, sizeof(rdpRailOrder));
}
return railOrder;
}
void rail_order_free(rdpRailOrder* rail_order)
void rail_order_free(rdpRailOrder* railOrder)
{
if (rail_order != NULL)
if (railOrder)
{
free(rail_order);
free(railOrder);
}
}

View File

@ -41,22 +41,25 @@ void rail_write_client_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* win
void rail_write_client_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* get_appid_req);
void rail_write_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbar_info);
BOOL rail_order_recv(rdpRailOrder* rail_order, wStream* s);
BOOL rail_order_recv(railPlugin* rail, wStream* s);
void rail_send_handshake_order(rdpRailOrder* rail_order);
void rail_send_client_status_order(rdpRailOrder* rail_order);
void rail_send_client_exec_order(rdpRailOrder* rail_order);
void rail_send_client_sysparam_order(rdpRailOrder* rail_order);
void rail_send_client_sysparams_order(rdpRailOrder* rail_order);
void rail_send_client_activate_order(rdpRailOrder* rail_order);
void rail_send_client_sysmenu_order(rdpRailOrder* rail_order);
void rail_send_client_syscommand_order(rdpRailOrder* rail_order);
void rail_send_client_notify_event_order(rdpRailOrder* rail_order);
void rail_send_client_window_move_order(rdpRailOrder* rail_order);
void rail_send_client_get_appid_req_order(rdpRailOrder* rail_order);
void rail_send_client_langbar_info_order(rdpRailOrder* rail_order);
void rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType);
void rail_send_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake);
void rail_send_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* handshakeEx);
void rail_send_client_status_order(railPlugin* rail, RAIL_CLIENT_STATUS_ORDER* clientStatus);
void rail_send_client_exec_order(railPlugin* rail, RAIL_EXEC_ORDER* exec);
void rail_send_client_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam);
void rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam);
void rail_send_client_activate_order(railPlugin* rail, RAIL_ACTIVATE_ORDER* activate);
void rail_send_client_sysmenu_order(railPlugin* rail, RAIL_SYSMENU_ORDER* sysmenu);
void rail_send_client_syscommand_order(railPlugin* rail, RAIL_SYSCOMMAND_ORDER* syscommand);
void rail_send_client_notify_event_order(railPlugin* rail, RAIL_NOTIFY_EVENT_ORDER* notifyEvent);
void rail_send_client_window_move_order(railPlugin* rail, RAIL_WINDOW_MOVE_ORDER* windowMove);
void rail_send_client_get_appid_req_order(railPlugin* rail, RAIL_GET_APPID_REQ_ORDER* getAppIdReq);
void rail_send_client_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORDER* langBarInfo);
rdpRailOrder* rail_order_new(void);
void rail_order_free(rdpRailOrder* rail_order);
void rail_order_free(rdpRailOrder* railOrder);
#endif /* __RAIL_ORDERS_H */

View File

@ -40,10 +40,15 @@ const char* const RAIL_ORDER_TYPE_STRINGS[] =
"Language Bar Info",
"Get Application ID Request",
"Get Application ID Response",
"Execute Result"
"Execute Result",
"",
"",
"",
"",
"",
""
};
void rail_string_to_unicode_string(char* string, RAIL_UNICODE_STRING* unicode_string)
{
WCHAR* buffer = NULL;
@ -55,7 +60,7 @@ void rail_string_to_unicode_string(char* string, RAIL_UNICODE_STRING* unicode_st
unicode_string->string = NULL;
unicode_string->length = 0;
if (string == NULL || strlen(string) < 1)
if (!string || strlen(string) < 1)
return;
length = ConvertToUnicode(CP_UTF8, 0, string, -1, &buffer, 0) * 2;
@ -68,8 +73,10 @@ BOOL rail_read_pdu_header(wStream* s, UINT16* orderType, UINT16* orderLength)
{
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
Stream_Read_UINT16(s, *orderType); /* orderType (2 bytes) */
Stream_Read_UINT16(s, *orderLength); /* orderLength (2 bytes) */
return TRUE;
}
@ -91,7 +98,9 @@ BOOL rail_read_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake)
{
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
Stream_Read_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */
return TRUE;
}
@ -100,3 +109,19 @@ void rail_write_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake)
Stream_Write_UINT32(s, handshake->buildNumber); /* buildNumber (4 bytes) */
}
BOOL rail_read_handshake_ex_order(wStream* s, RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{
if (Stream_GetRemainingLength(s) < 8)
return FALSE;
Stream_Read_UINT32(s, handshakeEx->buildNumber); /* buildNumber (4 bytes) */
Stream_Read_UINT32(s, handshakeEx->railHandshakeFlags); /* railHandshakeFlags (4 bytes) */
return TRUE;
}
void rail_write_handshake_ex_order(wStream* s, RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{
Stream_Write_UINT32(s, handshakeEx->buildNumber); /* buildNumber (4 bytes) */
Stream_Write_UINT32(s, handshakeEx->railHandshakeFlags); /* railHandshakeFlags (4 bytes) */
}

View File

@ -24,19 +24,13 @@
#include <freerdp/rail.h>
#ifdef WITH_DEBUG_RAIL
#define DEBUG_RAIL(fmt, ...) DEBUG_CLASS(RAIL, fmt, ## __VA_ARGS__)
#else
#define DEBUG_RAIL(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif
extern const char* const RAIL_ORDER_TYPE_STRINGS[];
#define RAIL_PDU_HEADER_LENGTH 4
/* Fixed length of PDUs, excluding variable lengths */
#define RAIL_HANDSHAKE_ORDER_LENGTH 4 /* fixed */
#define RAIL_HANDSHAKE_EX_ORDER_LENGTH 8 /* fixed */
#define RAIL_CLIENT_STATUS_ORDER_LENGTH 4 /* fixed */
#define RAIL_EXEC_ORDER_LENGTH 8 /* variable */
#define RAIL_SYSPARAM_ORDER_LENGTH 4 /* variable */
@ -74,6 +68,8 @@ typedef struct rdp_rail_order rdpRailOrder;
void rail_string_to_unicode_string(char* string, RAIL_UNICODE_STRING* unicode_string);
BOOL rail_read_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake);
void rail_write_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake);
BOOL rail_read_handshake_ex_order(wStream* s, RAIL_HANDSHAKE_EX_ORDER* handshakeEx);
void rail_write_handshake_ex_order(wStream* s, RAIL_HANDSHAKE_EX_ORDER* handshakeEx);
wStream* rail_pdu_init(int length);
BOOL rail_read_pdu_header(wStream* s, UINT16* orderType, UINT16* orderLength);

View File

@ -43,4 +43,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -27,50 +27,64 @@
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <winpr/stream.h>
#include <freerdp/utils/list.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/channels.h>
#include "rdpdr_main.h"
#include "devman.h"
DEVMAN* devman_new(rdpSvcPlugin* plugin)
static void devman_device_free(DEVICE* device)
{
IFCALL(device->Free, device);
}
DEVMAN* devman_new(rdpdrPlugin* rdpdr)
{
DEVMAN* devman;
devman = (DEVMAN*) malloc(sizeof(DEVMAN));
ZeroMemory(devman, sizeof(DEVMAN));
devman->plugin = plugin;
devman->plugin = (void*) rdpdr;
devman->id_sequence = 1;
devman->devices = list_new();
devman->devices = ListDictionary_New(TRUE);
ListDictionary_Object(devman->devices)->fnObjectFree =
(OBJECT_FREE_FN) devman_device_free;
return devman;
}
void devman_free(DEVMAN* devman)
{
DEVICE* device;
while ((device = (DEVICE*) list_dequeue(devman->devices)) != NULL)
IFCALL(device->Free, device);
list_free(devman->devices);
ListDictionary_Free(devman->devices);
free(devman);
}
static void devman_register_device(DEVMAN* devman, DEVICE* device)
{
device->id = devman->id_sequence++;
list_add(devman->devices, device);
void* key = NULL;
DEBUG_SVC("device %d.%s registered", device->id, device->name);
device->id = devman->id_sequence++;
key = (void*) (size_t) device->id;
ListDictionary_Add(devman->devices, key, device);
}
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id)
{
DEVICE* device = NULL;
void* key = (void*) (size_t) id;
device = (DEVICE*) ListDictionary_GetItemValue(devman->devices, key);
return device;
}
static char DRIVE_SERVICE_NAME[] = "drive";
@ -102,7 +116,7 @@ BOOL devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device)
fprintf(stderr, "Loading device service %s (static)\n", ServiceName);
entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL, "DeviceServiceEntry", 0);
if (entry == NULL)
if (!entry)
return FALSE;
ep.devman = devman;
@ -113,19 +127,3 @@ BOOL devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device)
return TRUE;
}
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id)
{
LIST_ITEM* item;
DEVICE* device;
for (item = devman->devices->head; item; item = item->next)
{
device = (DEVICE*) item->data;
if (device->id == id)
return device;
}
return NULL;
}

View File

@ -21,10 +21,12 @@
#ifndef FREERDP_CHANNEL_RDPDR_CLIENT_DEVMAN_H
#define FREERDP_CHANNEL_RDPDR_CLIENT_DEVMAN_H
#include "rdpdr_main.h"
BOOL devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device);
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id);
DEVMAN* devman_new(rdpSvcPlugin* plugin);
DEVMAN* devman_new(rdpdrPlugin* rdpdr);
void devman_free(DEVMAN* devman);
#endif /* FREERDP_CHANNEL_RDPDR_CLIENT_DEVMAN_H */

View File

@ -27,9 +27,7 @@
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/utils/svc_plugin.h>
#include "rdpdr_main.h"
#include "devman.h"
@ -37,8 +35,6 @@
static void irp_free(IRP* irp)
{
DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId);
Stream_Free(irp->input, TRUE);
Stream_Free(irp->output, TRUE);
@ -49,31 +45,28 @@ static void irp_complete(IRP* irp)
{
int pos;
DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId);
pos = Stream_GetPosition(irp->output);
Stream_SetPosition(irp->output, 12);
Stream_Write_UINT32(irp->output, irp->IoStatus);
Stream_SetPosition(irp->output, pos);
svc_plugin_send(irp->devman->plugin, irp->output);
rdpdr_send((rdpdrPlugin*) irp->devman->plugin, irp->output);
irp->output = NULL;
irp_free(irp);
}
IRP* irp_new(DEVMAN* devman, wStream* data_in)
IRP* irp_new(DEVMAN* devman, wStream* s)
{
IRP* irp;
UINT32 DeviceId;
DEVICE* device;
Stream_Read_UINT32(data_in, DeviceId);
Stream_Read_UINT32(s, DeviceId);
device = devman_get_device_by_id(devman, DeviceId);
if (device == NULL)
if (!device)
{
DEBUG_WARN("unknown DeviceId %d", DeviceId);
return NULL;
}
@ -82,11 +75,11 @@ IRP* irp_new(DEVMAN* devman, wStream* data_in)
irp->device = device;
irp->devman = devman;
Stream_Read_UINT32(data_in, irp->FileId);
Stream_Read_UINT32(data_in, irp->CompletionId);
Stream_Read_UINT32(data_in, irp->MajorFunction);
Stream_Read_UINT32(data_in, irp->MinorFunction);
irp->input = data_in;
Stream_Read_UINT32(s, irp->FileId);
Stream_Read_UINT32(s, irp->CompletionId);
Stream_Read_UINT32(s, irp->MajorFunction);
Stream_Read_UINT32(s, irp->MinorFunction);
irp->input = s;
irp->output = Stream_New(NULL, 256);
Stream_Write_UINT16(irp->output, RDPDR_CTYP_CORE);
@ -98,8 +91,5 @@ IRP* irp_new(DEVMAN* devman, wStream* data_in)
irp->Complete = irp_complete;
irp->Discard = irp_free;
DEBUG_SVC("DeviceId %d FileId %d CompletionId %d MajorFunction 0x%X MinorFunction 0x%x",
irp->device->id, irp->FileId, irp->CompletionId, irp->MajorFunction, irp->MinorFunction);
return irp;
}

View File

@ -23,6 +23,6 @@
#include "rdpdr_main.h"
IRP* irp_new(DEVMAN* devman, wStream* data_in);
IRP* irp_new(DEVMAN* devman, wStream* s);
#endif /* FREERDP_CHANNEL_RDPDR_CLIENT_IRP_H */

View File

@ -26,8 +26,8 @@
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/utils/svc_plugin.h>
#include "rdpdr_main.h"
#include "rdpdr_capabilities.h"
@ -162,7 +162,6 @@ void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s)
break;
default:
DEBUG_WARN("Unknown capabilityType %d", capabilityType);
break;
}
}
@ -186,5 +185,5 @@ void rdpdr_send_capability_response(rdpdrPlugin* rdpdr)
rdpdr_write_drive_capset(rdpdr, s);
rdpdr_write_smartcard_capset(rdpdr, s);
svc_plugin_send((rdpSvcPlugin*)rdpdr, s);
rdpdr_send(rdpdr, s);
}

View File

@ -23,7 +23,7 @@
#include "rdpdr_main.h"
void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* data_in);
void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s);
void rdpdr_send_capability_response(rdpdrPlugin* rdpdr);
#endif /* FREERDP_CHANNEL_RDPDR_CLIENT_CAPABILITIES_H */

View File

@ -27,12 +27,11 @@
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <winpr/stream.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/utils/svc_plugin.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@ -45,15 +44,14 @@
#include "rdpdr_main.h"
static void rdpdr_process_connect(rdpSvcPlugin* plugin)
static void rdpdr_process_connect(rdpdrPlugin* rdpdr)
{
int index;
RDPDR_DEVICE* device;
rdpSettings* settings;
rdpdrPlugin* rdpdr = (rdpdrPlugin*) plugin;
rdpdr->devman = devman_new(plugin);
settings = (rdpSettings*) plugin->channel_entry_points.pExtendedData;
rdpdr->devman = devman_new(rdpdr);
settings = (rdpSettings*) rdpdr->channelEntryPoints.pExtendedData;
strncpy(rdpdr->computerName, settings->ComputerName, sizeof(rdpdr->computerName) - 1);
@ -64,34 +62,32 @@ static void rdpdr_process_connect(rdpSvcPlugin* plugin)
}
}
static void rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, wStream* s)
{
Stream_Read_UINT16(data_in, rdpdr->versionMajor);
Stream_Read_UINT16(data_in, rdpdr->versionMinor);
Stream_Read_UINT32(data_in, rdpdr->clientID);
DEBUG_SVC("version %d.%d clientID %d", rdpdr->versionMajor, rdpdr->versionMinor, rdpdr->clientID);
Stream_Read_UINT16(s, rdpdr->versionMajor);
Stream_Read_UINT16(s, rdpdr->versionMinor);
Stream_Read_UINT32(s, rdpdr->clientID);
}
static void rdpdr_send_client_announce_reply(rdpdrPlugin* rdpdr)
{
wStream* data_out;
wStream* s;
data_out = Stream_New(NULL, 12);
s = Stream_New(NULL, 12);
Stream_Write_UINT16(data_out, RDPDR_CTYP_CORE);
Stream_Write_UINT16(data_out, PAKID_CORE_CLIENTID_CONFIRM);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
Stream_Write_UINT16(s, PAKID_CORE_CLIENTID_CONFIRM);
Stream_Write_UINT16(data_out, rdpdr->versionMajor);
Stream_Write_UINT16(data_out, rdpdr->versionMinor);
Stream_Write_UINT32(data_out, (UINT32) rdpdr->clientID);
Stream_Write_UINT16(s, rdpdr->versionMajor);
Stream_Write_UINT16(s, rdpdr->versionMinor);
Stream_Write_UINT32(s, (UINT32) rdpdr->clientID);
svc_plugin_send((rdpSvcPlugin*) rdpdr, data_out);
rdpdr_send(rdpdr, s);
}
static void rdpdr_send_client_name_request(rdpdrPlugin* rdpdr)
{
wStream* data_out;
wStream* s;
WCHAR* computerNameW = NULL;
size_t computerNameLenW;
@ -100,70 +96,74 @@ static void rdpdr_send_client_name_request(rdpdrPlugin* rdpdr)
computerNameLenW = ConvertToUnicode(CP_UTF8, 0, rdpdr->computerName, -1, &computerNameW, 0) * 2;
data_out = Stream_New(NULL, 16 + computerNameLenW + 2);
s = Stream_New(NULL, 16 + computerNameLenW + 2);
Stream_Write_UINT16(data_out, RDPDR_CTYP_CORE);
Stream_Write_UINT16(data_out, PAKID_CORE_CLIENT_NAME);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
Stream_Write_UINT16(s, PAKID_CORE_CLIENT_NAME);
Stream_Write_UINT32(data_out, 1); /* unicodeFlag, 0 for ASCII and 1 for Unicode */
Stream_Write_UINT32(data_out, 0); /* codePage, must be set to zero */
Stream_Write_UINT32(data_out, computerNameLenW + 2); /* computerNameLen, including null terminator */
Stream_Write(data_out, computerNameW, computerNameLenW);
Stream_Write_UINT16(data_out, 0); /* null terminator */
Stream_Write_UINT32(s, 1); /* unicodeFlag, 0 for ASCII and 1 for Unicode */
Stream_Write_UINT32(s, 0); /* codePage, must be set to zero */
Stream_Write_UINT32(s, computerNameLenW + 2); /* computerNameLen, including null terminator */
Stream_Write(s, computerNameW, computerNameLenW);
Stream_Write_UINT16(s, 0); /* null terminator */
free(computerNameW);
svc_plugin_send((rdpSvcPlugin*) rdpdr, data_out);
rdpdr_send(rdpdr, s);
}
static void rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 versionMajor;
UINT16 versionMinor;
UINT32 clientID;
Stream_Read_UINT16(data_in, versionMajor);
Stream_Read_UINT16(data_in, versionMinor);
Stream_Read_UINT32(data_in, clientID);
Stream_Read_UINT16(s, versionMajor);
Stream_Read_UINT16(s, versionMinor);
Stream_Read_UINT32(s, clientID);
if (versionMajor != rdpdr->versionMajor || versionMinor != rdpdr->versionMinor)
{
DEBUG_WARN("unmatched version %d.%d", versionMajor, versionMinor);
rdpdr->versionMajor = versionMajor;
rdpdr->versionMinor = versionMinor;
}
if (clientID != rdpdr->clientID)
{
DEBUG_WARN("unmatched clientID %d", clientID);
rdpdr->clientID = clientID;
}
}
static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL user_loggedon)
static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL userLoggedOn)
{
int i;
int pos;
BYTE c;
int pos;
int index;
wStream* s;
UINT32 count;
int data_len;
int count_pos;
wStream* data_out;
DEVICE* device;
LIST_ITEM* item;
int keyCount;
ULONG_PTR* pKeys;
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_DEVICELIST_ANNOUNCE);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
Stream_Write_UINT16(s, PAKID_CORE_DEVICELIST_ANNOUNCE);
count_pos = Stream_GetPosition(data_out);
count_pos = Stream_GetPosition(s);
count = 0;
Stream_Seek_UINT32(data_out); /* deviceCount */
for (item = rdpdr->devman->devices->head; item; item = item->next)
Stream_Seek_UINT32(s); /* deviceCount */
pKeys = NULL;
keyCount = ListDictionary_GetKeys(rdpdr->devman->devices, &pKeys);
for (index = 0; index < keyCount; index++)
{
device = (DEVICE*) item->data;
device = (DEVICE*) ListDictionary_GetItemValue(rdpdr->devman->devices, (void*) pKeys[index]);
/**
* 1. versionMinor 0x0005 doesn't send PAKID_CORE_USER_LOGGEDON
@ -173,29 +173,29 @@ static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use
*/
if ((rdpdr->versionMinor == 0x0005) ||
(device->type == RDPDR_DTYP_SMARTCARD) || user_loggedon)
(device->type == RDPDR_DTYP_SMARTCARD) || userLoggedOn)
{
data_len = (device->data == NULL ? 0 : Stream_GetPosition(device->data));
Stream_EnsureRemainingCapacity(data_out, 20 + data_len);
Stream_EnsureRemainingCapacity(s, 20 + data_len);
Stream_Write_UINT32(data_out, device->type); /* deviceType */
Stream_Write_UINT32(data_out, device->id); /* deviceID */
strncpy((char*) Stream_Pointer(data_out), device->name, 8);
Stream_Write_UINT32(s, device->type); /* deviceType */
Stream_Write_UINT32(s, device->id); /* deviceID */
strncpy((char*) Stream_Pointer(s), device->name, 8);
for (i = 0; i < 8; i++)
{
Stream_Peek_UINT8(data_out, c);
Stream_Peek_UINT8(s, c);
if (c > 0x7F)
Stream_Write_UINT8(data_out, '_');
Stream_Write_UINT8(s, '_');
else
Stream_Seek_UINT8(data_out);
Stream_Seek_UINT8(s);
}
Stream_Write_UINT32(data_out, data_len);
Stream_Write_UINT32(s, data_len);
if (data_len > 0)
Stream_Write(data_out, Stream_Buffer(device->data), data_len);
Stream_Write(s, Stream_Buffer(device->data), data_len);
count++;
@ -204,22 +204,25 @@ static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use
}
}
pos = Stream_GetPosition(data_out);
Stream_SetPosition(data_out, count_pos);
Stream_Write_UINT32(data_out, count);
Stream_SetPosition(data_out, pos);
Stream_SealLength(data_out);
if (pKeys)
free(pKeys);
svc_plugin_send((rdpSvcPlugin*) rdpdr, data_out);
pos = Stream_GetPosition(s);
Stream_SetPosition(s, count_pos);
Stream_Write_UINT32(s, count);
Stream_SetPosition(s, pos);
Stream_SealLength(s);
rdpdr_send(rdpdr, s);
}
static BOOL rdpdr_process_irp(rdpdrPlugin* rdpdr, wStream* data_in)
static BOOL rdpdr_process_irp(rdpdrPlugin* rdpdr, wStream* s)
{
IRP* irp;
irp = irp_new(rdpdr->devman, data_in);
irp = irp_new(rdpdr->devman, s);
if (irp == NULL)
if (!irp)
return FALSE;
IFCALL(irp->device->IRPRequest, irp->device, irp);
@ -227,87 +230,312 @@ static BOOL rdpdr_process_irp(rdpdrPlugin* rdpdr, wStream* data_in)
return TRUE;
}
static void rdpdr_process_receive(rdpSvcPlugin* plugin, wStream* data_in)
static void rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 component;
UINT16 packetID;
UINT32 deviceID;
UINT32 status;
rdpdrPlugin* rdpdr = (rdpdrPlugin*) plugin;
Stream_Read_UINT16(data_in, component);
Stream_Read_UINT16(data_in, packetID);
Stream_Read_UINT16(s, component);
Stream_Read_UINT16(s, packetID);
if (component == RDPDR_CTYP_CORE)
{
switch (packetID)
{
case PAKID_CORE_SERVER_ANNOUNCE:
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_SERVER_ANNOUNCE");
rdpdr_process_server_announce_request(rdpdr, data_in);
rdpdr_process_server_announce_request(rdpdr, s);
rdpdr_send_client_announce_reply(rdpdr);
rdpdr_send_client_name_request(rdpdr);
break;
case PAKID_CORE_SERVER_CAPABILITY:
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_SERVER_CAPABILITY");
rdpdr_process_capability_request(rdpdr, data_in);
rdpdr_process_capability_request(rdpdr, s);
rdpdr_send_capability_response(rdpdr);
break;
case PAKID_CORE_CLIENTID_CONFIRM:
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_CLIENTID_CONFIRM");
rdpdr_process_server_clientid_confirm(rdpdr, data_in);
rdpdr_process_server_clientid_confirm(rdpdr, s);
rdpdr_send_device_list_announce_request(rdpdr, FALSE);
break;
case PAKID_CORE_USER_LOGGEDON:
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_USER_LOGGEDON");
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
break;
case PAKID_CORE_DEVICE_REPLY:
/* connect to a specific resource */
Stream_Read_UINT32(data_in, deviceID);
Stream_Read_UINT32(data_in, status);
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_DEVICE_REPLY (deviceID=%d status=0x%08X)", deviceID, status);
Stream_Read_UINT32(s, deviceID);
Stream_Read_UINT32(s, status);
break;
case PAKID_CORE_DEVICE_IOREQUEST:
DEBUG_SVC("RDPDR_CTYP_CORE / PAKID_CORE_DEVICE_IOREQUEST");
if (rdpdr_process_irp(rdpdr, data_in))
data_in = NULL;
if (rdpdr_process_irp(rdpdr, s))
s = NULL;
break;
default:
DEBUG_WARN("RDPDR_CTYP_CORE / unknown packetID: 0x%02X", packetID);
break;
}
}
else if (component == RDPDR_CTYP_PRN)
{
DEBUG_SVC("RDPDR_CTYP_PRN");
}
else
{
DEBUG_WARN("RDPDR component: 0x%02X packetID: 0x%02X", component, packetID);
}
Stream_Free(data_in, TRUE);
Stream_Free(s, TRUE);
}
static void rdpdr_process_event(rdpSvcPlugin* plugin, wMessage* event)
/****************************************************************************************/
static wListDictionary* g_InitHandles;
static wListDictionary* g_OpenHandles;
void rdpdr_add_init_handle_data(void* pInitHandle, void* pUserData)
{
freerdp_event_free(event);
if (!g_InitHandles)
g_InitHandles = ListDictionary_New(TRUE);
ListDictionary_Add(g_InitHandles, pInitHandle, pUserData);
}
static void rdpdr_process_terminate(rdpSvcPlugin* plugin)
void* rdpdr_get_init_handle_data(void* pInitHandle)
{
rdpdrPlugin* rdpdr = (rdpdrPlugin*) plugin;
void* pUserData = NULL;
pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
return pUserData;
}
devman_free(rdpdr->devman);
free(plugin);
void rdpdr_remove_init_handle_data(void* pInitHandle)
{
ListDictionary_Remove(g_InitHandles, pInitHandle);
}
void rdpdr_add_open_handle_data(DWORD openHandle, void* pUserData)
{
void* pOpenHandle = (void*) (size_t) openHandle;
if (!g_OpenHandles)
g_OpenHandles = ListDictionary_New(TRUE);
ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData);
}
void* rdpdr_get_open_handle_data(DWORD openHandle)
{
void* pUserData = NULL;
void* pOpenHandle = (void*) (size_t) openHandle;
pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
return pUserData;
}
void rdpdr_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
}
int rdpdr_send(rdpdrPlugin* rdpdr, wStream* s)
{
UINT32 status = 0;
rdpdrPlugin* plugin = (rdpdrPlugin*) rdpdr;
if (!plugin)
status = CHANNEL_RC_BAD_INIT_HANDLE;
else
status = plugin->channelEntryPoints.pVirtualChannelWrite(plugin->OpenHandle,
Stream_Buffer(s), Stream_GetPosition(s), s);
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
fprintf(stderr, "rdpdr_send: VirtualChannelWrite failed %d\n", status);
}
return status;
}
static void rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr,
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
wStream* data_in;
if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
{
/*
* According to MS-RDPBCGR 2.2.6.1, "All virtual channel traffic MUST be suspended.
* This flag is only valid in server-to-client virtual channel traffic. It MUST be
* ignored in client-to-server data." Thus it would be best practice to cease data
* transmission. However, simply returning here avoids a crash.
*/
return;
}
if (dataFlags & CHANNEL_FLAG_FIRST)
{
if (rdpdr->data_in != NULL)
Stream_Free(rdpdr->data_in, TRUE);
rdpdr->data_in = Stream_New(NULL, totalLength);
}
data_in = rdpdr->data_in;
Stream_EnsureRemainingCapacity(data_in, (int) dataLength);
Stream_Write(data_in, pData, dataLength);
if (dataFlags & CHANNEL_FLAG_LAST)
{
if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
{
fprintf(stderr, "svc_plugin_process_received: read error\n");
}
rdpdr->data_in = NULL;
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(rdpdr->MsgPipe->In, NULL, 0, (void*) data_in, NULL);
}
}
static void rdpdr_virtual_channel_open_event(UINT32 openHandle, UINT32 event,
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
rdpdrPlugin* rdpdr;
rdpdr = (rdpdrPlugin*) rdpdr_get_open_handle_data(openHandle);
if (!rdpdr)
{
fprintf(stderr, "rdpdr_virtual_channel_open_event: error no match\n");
return;
}
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, totalLength, dataFlags);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
Stream_Free((wStream*) pData, TRUE);
break;
case CHANNEL_EVENT_USER:
break;
}
}
static void* rdpdr_virtual_channel_client_thread(void* arg)
{
wStream* data;
wMessage message;
rdpdrPlugin* rdpdr = (rdpdrPlugin*) arg;
rdpdr_process_connect(rdpdr);
while (1)
{
if (!MessageQueue_Wait(rdpdr->MsgPipe->In))
break;
if (MessageQueue_Peek(rdpdr->MsgPipe->In, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
{
data = (wStream*) message.wParam;
rdpdr_process_receive(rdpdr, data);
}
}
}
ExitThread(0);
return NULL;
}
static void rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, void* pData, UINT32 dataLength)
{
UINT32 status;
status = rdpdr->channelEntryPoints.pVirtualChannelOpen(rdpdr->InitHandle,
&rdpdr->OpenHandle, rdpdr->channelDef.name, rdpdr_virtual_channel_open_event);
rdpdr_add_open_handle_data(rdpdr->OpenHandle, rdpdr);
if (status != CHANNEL_RC_OK)
{
fprintf(stderr, "rdpdr_virtual_channel_event_connected: open failed: status: %d\n", status);
return;
}
rdpdr->MsgPipe = MessagePipe_New();
rdpdr->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpdr_virtual_channel_client_thread, (void*) rdpdr, 0, NULL);
}
static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr)
{
MessagePipe_PostQuit(rdpdr->MsgPipe, 0);
WaitForSingleObject(rdpdr->thread, INFINITE);
MessagePipe_Free(rdpdr->MsgPipe);
CloseHandle(rdpdr->thread);
rdpdr->channelEntryPoints.pVirtualChannelClose(rdpdr->OpenHandle);
if (rdpdr->data_in)
{
Stream_Free(rdpdr->data_in, TRUE);
rdpdr->data_in = NULL;
}
if (rdpdr->devman)
{
devman_free(rdpdr->devman);
rdpdr->devman = NULL;
}
rdpdr_remove_open_handle_data(rdpdr->OpenHandle);
rdpdr_remove_init_handle_data(rdpdr->InitHandle);
}
static void rdpdr_virtual_channel_init_event(void* pInitHandle, UINT32 event, void* pData, UINT32 dataLength)
{
rdpdrPlugin* rdpdr;
rdpdr = (rdpdrPlugin*) rdpdr_get_init_handle_data(pInitHandle);
if (!rdpdr)
{
fprintf(stderr, "rdpdr_virtual_channel_init_event: error no match\n");
return;
}
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength);
break;
case CHANNEL_EVENT_DISCONNECTED:
break;
case CHANNEL_EVENT_TERMINATED:
rdpdr_virtual_channel_event_terminated(rdpdr);
break;
}
}
/* rdpdr is always built-in */
@ -315,24 +543,24 @@ static void rdpdr_process_terminate(rdpSvcPlugin* plugin)
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
rdpdrPlugin* _p;
rdpdrPlugin* rdpdr;
_p = (rdpdrPlugin*) malloc(sizeof(rdpdrPlugin));
ZeroMemory(_p, sizeof(rdpdrPlugin));
rdpdr = (rdpdrPlugin*) malloc(sizeof(rdpdrPlugin));
ZeroMemory(rdpdr, sizeof(rdpdrPlugin));
_p->plugin.channel_def.options =
rdpdr->channelDef.options =
CHANNEL_OPTION_INITIALIZED |
CHANNEL_OPTION_ENCRYPT_RDP |
CHANNEL_OPTION_COMPRESS_RDP;
strcpy(_p->plugin.channel_def.name, "rdpdr");
strcpy(rdpdr->channelDef.name, "rdpdr");
_p->plugin.connect_callback = rdpdr_process_connect;
_p->plugin.receive_callback = rdpdr_process_receive;
_p->plugin.event_callback = rdpdr_process_event;
_p->plugin.terminate_callback = rdpdr_process_terminate;
CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, pEntryPoints->cbSize);
svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints);
rdpdr->channelEntryPoints.pVirtualChannelInit(&rdpdr->InitHandle,
&rdpdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpdr_virtual_channel_init_event);
rdpdr_add_init_handle_data(rdpdr->InitHandle, (void*) rdpdr);
return 1;
}

View File

@ -21,14 +21,30 @@
#ifndef FREERDP_CHANNEL_RDPDR_CLIENT_MAIN_H
#define FREERDP_CHANNEL_RDPDR_CLIENT_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <freerdp/api.h>
#include <freerdp/svc.h>
#include <freerdp/addin.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/utils/svc_plugin.h>
typedef struct rdpdr_plugin rdpdrPlugin;
struct rdpdr_plugin
{
rdpSvcPlugin plugin;
CHANNEL_DEF channelDef;
CHANNEL_ENTRY_POINTS_EX channelEntryPoints;
HANDLE thread;
wStream* data_in;
void* InitHandle;
UINT32 OpenHandle;
wMessagePipe* MsgPipe;
DEVMAN* devman;
@ -38,4 +54,6 @@ struct rdpdr_plugin
char computerName[256];
};
int rdpdr_send(rdpdrPlugin* rdpdr, wStream* s);
#endif /* FREERDP_CHANNEL_RDPDR_CLIENT_MAIN_H */

View File

@ -32,4 +32,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -41,9 +41,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -0,0 +1,23 @@
# 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("rdpgfx")
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -0,0 +1,13 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT OFF)
define_channel_options(NAME "rdpgfx" TYPE "dynamic"
DESCRIPTION "Graphics Pipeline Extension"
SPECIFICATIONS "[MS-RDPEGFX]"
DEFAULT ${OPTION_DEFAULT})
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})

View File

@ -0,0 +1,47 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP 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.
define_channel_client("rdpgfx")
set(${MODULE_PREFIX}_SRCS
rdpgfx_main.c
rdpgfx_main.h
rdpgfx_common.c
rdpgfx_common.h)
include_directories(..)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-common freerdp-utils)
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE winpr
MODULES winpr-sysinfo)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -0,0 +1,101 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Graphics Pipeline Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/stream.h>
#include "rdpgfx_common.h"
int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* point16)
{
Stream_Read_UINT16(s, point16->x); /* x (2 bytes) */
Stream_Read_UINT16(s, point16->y); /* y (2 bytes) */
return 0;
}
int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16)
{
Stream_Write_UINT16(s, point16->x); /* x (2 bytes) */
Stream_Write_UINT16(s, point16->y); /* y (2 bytes) */
return 0;
}
int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16)
{
Stream_Read_UINT16(s, rect16->left); /* left (2 bytes) */
Stream_Read_UINT16(s, rect16->top); /* top (2 bytes) */
Stream_Read_UINT16(s, rect16->right); /* right (2 bytes) */
Stream_Read_UINT16(s, rect16->bottom); /* bottom (2 bytes) */
return 0;
}
int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16)
{
Stream_Write_UINT16(s, rect16->left); /* left (2 bytes) */
Stream_Write_UINT16(s, rect16->top); /* top (2 bytes) */
Stream_Write_UINT16(s, rect16->right); /* right (2 bytes) */
Stream_Write_UINT16(s, rect16->bottom); /* bottom (2 bytes) */
return 0;
}
int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32)
{
Stream_Read_UINT8(s, color32->B); /* B (1 byte) */
Stream_Read_UINT8(s, color32->G); /* G (1 byte) */
Stream_Read_UINT8(s, color32->R); /* R (1 byte) */
Stream_Read_UINT8(s, color32->XA); /* XA (1 byte) */
return 0;
}
int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32)
{
Stream_Write_UINT8(s, color32->B); /* B (1 byte) */
Stream_Write_UINT8(s, color32->G); /* G (1 byte) */
Stream_Write_UINT8(s, color32->R); /* R (1 byte) */
Stream_Write_UINT8(s, color32->XA); /* XA (1 byte) */
return 0;
}
int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header)
{
Stream_Read_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
Stream_Read_UINT16(s, header->flags); /* flags (2 bytes) */
Stream_Read_UINT16(s, header->pduLength); /* pduLength (4 bytes) */
return 0;
}
int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header)
{
Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */
Stream_Write_UINT16(s, header->pduLength); /* pduLength (4 bytes) */
return 0;
}

View File

@ -0,0 +1,38 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Graphics Pipeline 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_RDPGFX_CLIENT_COMMON_H
#define FREERDP_CHANNEL_RDPGFX_CLIENT_COMMON_H
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/channels/rdpgfx.h>
int rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* point16);
int rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16);
int rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16);
int rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16);
int rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32);
int rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32);
int rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header);
int rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header);
#endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_COMMON_H */

View File

@ -0,0 +1,207 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Graphics Pipeline 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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/wlog.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include <winpr/cmdline.h>
#include <winpr/collections.h>
#include <freerdp/addin.h>
#include "rdpgfx_common.h"
#include "rdpgfx_main.h"
struct _RDPGFX_CHANNEL_CALLBACK
{
IWTSVirtualChannelCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
IWTSVirtualChannel* channel;
};
typedef struct _RDPGFX_CHANNEL_CALLBACK RDPGFX_CHANNEL_CALLBACK;
struct _RDPGFX_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
RDPGFX_CHANNEL_CALLBACK* channel_callback;
};
typedef struct _RDPGFX_LISTENER_CALLBACK RDPGFX_LISTENER_CALLBACK;
struct _RDPGFX_PLUGIN
{
IWTSPlugin iface;
IWTSListener* listener;
RDPGFX_LISTENER_CALLBACK* listener_callback;
};
typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN;
int rdpgfx_recv_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
{
return 0;
}
static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT32 cbSize, BYTE* pBuffer)
{
wStream* s;
int status = 0;
RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback;
fprintf(stderr, "RdpGfxOnDataReceived\n");
s = Stream_New(pBuffer, cbSize);
status = rdpgfx_recv_pdu(callback, s);
Stream_Free(s, FALSE);
return status;
}
static int rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback)
{
RDPGFX_CHANNEL_CALLBACK* callback = (RDPGFX_CHANNEL_CALLBACK*) pChannelCallback;
free(callback);
return 0;
}
static int rdpgfx_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
IWTSVirtualChannel* pChannel, BYTE* Data, int* pbAccept,
IWTSVirtualChannelCallback** ppCallback)
{
RDPGFX_CHANNEL_CALLBACK* callback;
RDPGFX_LISTENER_CALLBACK* listener_callback = (RDPGFX_LISTENER_CALLBACK*) pListenerCallback;
callback = (RDPGFX_CHANNEL_CALLBACK*) malloc(sizeof(RDPGFX_CHANNEL_CALLBACK));
ZeroMemory(callback, sizeof(RDPGFX_CHANNEL_CALLBACK));
callback->iface.OnDataReceived = rdpgfx_on_data_received;
callback->iface.OnClose = rdpgfx_on_close;
callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel;
listener_callback->channel_callback = callback;
*ppCallback = (IWTSVirtualChannelCallback*) callback;
fprintf(stderr, "RdpGfxOnNewChannelConnection\n");
return 0;
}
static int rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{
int status;
RDPGFX_PLUGIN* rdpgfx = (RDPGFX_PLUGIN*) pPlugin;
rdpgfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*) malloc(sizeof(RDPGFX_LISTENER_CALLBACK));
ZeroMemory(rdpgfx->listener_callback, sizeof(RDPGFX_LISTENER_CALLBACK));
rdpgfx->listener_callback->iface.OnNewChannelConnection = rdpgfx_on_new_channel_connection;
rdpgfx->listener_callback->plugin = pPlugin;
rdpgfx->listener_callback->channel_mgr = pChannelMgr;
status = pChannelMgr->CreateListener(pChannelMgr, RDPGFX_DVC_CHANNEL_NAME, 0,
(IWTSListenerCallback*) rdpgfx->listener_callback, &(rdpgfx->listener));
rdpgfx->listener->pInterface = rdpgfx->iface.pInterface;
fprintf(stderr, "RdpGfxInitialize\n");
return status;
}
static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin)
{
RDPGFX_PLUGIN* rdpgfx = (RDPGFX_PLUGIN*) pPlugin;
if (rdpgfx->listener_callback)
free(rdpgfx->listener_callback);
free(rdpgfx);
return 0;
}
/**
* Channel Client Interface
*/
UINT32 rdpgfx_get_version(RdpgfxClientContext* context)
{
//RDPGFX_PLUGIN* rdpgfx = (RDPGFX_PLUGIN*) context->handle;
return 0;
}
#ifdef STATIC_CHANNELS
#define DVCPluginEntry rdpgfx_DVCPluginEntry
#endif
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
int error = 0;
RDPGFX_PLUGIN* rdpgfx;
RdpgfxClientContext* context;
rdpgfx = (RDPGFX_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "rdpgfx");
if (!rdpgfx)
{
rdpgfx = (RDPGFX_PLUGIN*) malloc(sizeof(RDPGFX_PLUGIN));
ZeroMemory(rdpgfx, sizeof(RDPGFX_PLUGIN));
rdpgfx->iface.Initialize = rdpgfx_plugin_initialize;
rdpgfx->iface.Connected = NULL;
rdpgfx->iface.Disconnected = NULL;
rdpgfx->iface.Terminated = rdpgfx_plugin_terminated;
context = (RdpgfxClientContext*) malloc(sizeof(RdpgfxClientContext));
context->handle = (void*) rdpgfx;
context->GetVersion = rdpgfx_get_version;
rdpgfx->iface.pInterface = (void*) context;
fprintf(stderr, "RdpGfxDVCPluginEntry\n");
error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpgfx", (IWTSPlugin*) rdpgfx);
}
return error;
}

View File

@ -0,0 +1,36 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Graphics Pipeline 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_RDPGFX_CLIENT_MAIN_H
#define FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <freerdp/dvc.h>
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <freerdp/client/rdpgfx.h>
#endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H */

View File

@ -37,6 +37,8 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
if(WITH_ALSA)
@ -44,7 +46,7 @@ if(WITH_ALSA)
endif()
if(WITH_IOSAUDIO)
add_channel_client_subsystem($(MODULE_PREFIX) $(CHANNEL_NAME) "ios" "")
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "ios" "")
endif()
if(WITH_PULSE)

View File

@ -41,8 +41,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ALSA_LIBRARIES})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/ALSA")

View File

@ -45,8 +45,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/ios")

View File

@ -45,8 +45,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/Mac")

View File

@ -38,6 +38,4 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${OPENSLES_LIBRARIES})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)

View File

@ -36,8 +36,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/Pulse")

View File

@ -4,6 +4,7 @@
*
* Copyright 2009-2011 Jay Sorg
* Copyright 2010-2011 Vic Lee
* Copyright 2012-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.
@ -34,6 +35,8 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/print.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/cmdline.h>
#include <winpr/sysinfo.h>
#include <winpr/collections.h>
@ -41,9 +44,8 @@
#include <freerdp/types.h>
#include <freerdp/addin.h>
#include <freerdp/constants.h>
#include <winpr/stream.h>
#include <freerdp/utils/debug.h>
#include <freerdp/utils/signal.h>
#include <freerdp/utils/svc_plugin.h>
#include "rdpsnd_main.h"
@ -51,10 +53,16 @@
struct rdpsnd_plugin
{
rdpSvcPlugin plugin;
CHANNEL_DEF channelDef;
CHANNEL_ENTRY_POINTS_EX channelEntryPoints;
HANDLE thread;
wMessageQueue* queue;
wStream* data_in;
void* InitHandle;
UINT32 OpenHandle;
wMessagePipe* MsgPipe;
HANDLE ScheduleThread;
BYTE cBlockNo;
int wCurrentFormatNo;
@ -96,10 +104,10 @@ static void* rdpsnd_schedule_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(rdpsnd->queue))
if (!MessageQueue_Wait(rdpsnd->MsgPipe->Out))
break;
if (!MessageQueue_Peek(rdpsnd->queue, &message, TRUE))
if (!MessageQueue_Peek(rdpsnd->MsgPipe->Out, &message, TRUE))
break;
if (message.id == WMQ_QUIT)
@ -134,7 +142,7 @@ void rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
Stream_Write_UINT16(pdu, HIGH_QUALITY); /* wQualityMode */
Stream_Write_UINT16(pdu, 0); /* Reserved */
svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
@ -250,7 +258,7 @@ void rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
Stream_Write(pdu, clientFormat->data, clientFormat->cbSize);
}
svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
@ -289,8 +297,15 @@ void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
Stream_Read_UINT16(s, format->wBitsPerSample); /* wBitsPerSample */
Stream_Read_UINT16(s, format->cbSize); /* cbSize */
format->data = (BYTE*) malloc(format->cbSize);
Stream_Read(s, format->data, format->cbSize);
if (format->cbSize > 0)
{
format->data = (BYTE*) malloc(format->cbSize);
Stream_Read(s, format->data, format->cbSize);
}
else
{
format->data = NULL;
}
}
rdpsnd_select_supported_audio_formats(rdpsnd);
@ -315,7 +330,7 @@ void rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, U
Stream_Write_UINT16(pdu, wTimeStamp);
Stream_Write_UINT16(pdu, wPackSize);
svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
static void rdpsnd_recv_training_pdu(rdpsndPlugin* rdpsnd, wStream* s)
@ -381,12 +396,12 @@ void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE
Stream_Write_UINT8(pdu, cConfirmedBlockNo); /* cConfirmedBlockNo */
Stream_Write_UINT8(pdu, 0); /* bPad */
svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
static void rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
{
MessageQueue_Post(device->rdpsnd->queue, NULL, 0, (void*) wave, NULL);
MessageQueue_Post(device->rdpsnd->MsgPipe->Out, NULL, 0, (void*) wave, NULL);
}
static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
@ -453,8 +468,6 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd)
{
DEBUG_SVC("server closes.");
if (rdpsnd->device)
{
IFCALL(rdpsnd->device->Close, rdpsnd->device);
@ -468,7 +481,6 @@ static void rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s)
UINT32 dwVolume;
Stream_Read_UINT32(s, dwVolume);
DEBUG_SVC("dwVolume 0x%X", dwVolume);
if (rdpsnd->device)
{
@ -476,11 +488,10 @@ static void rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s)
}
}
static void rdpsnd_recv_pdu(rdpSvcPlugin* plugin, wStream* s)
static void rdpsnd_recv_pdu(rdpsndPlugin* rdpsnd, wStream* s)
{
BYTE msgType;
UINT16 BodySize;
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin;
if (rdpsnd->expectingWave)
{
@ -645,20 +656,17 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
}
static void rdpsnd_process_connect(rdpSvcPlugin* plugin)
static void rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
{
ADDIN_ARGV* args;
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin;
DEBUG_SVC("connecting");
rdpsnd->latency = -1;
rdpsnd->queue = MessageQueue_New();
rdpsnd->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
(void*) plugin, 0, NULL);
args = (ADDIN_ARGV*) plugin->channel_entry_points.pExtendedData;
rdpsnd->ScheduleThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
(void*) rdpsnd, 0, NULL);
args = (ADDIN_ARGV*) rdpsnd->channelEntryPoints.pExtendedData;
if (args)
rdpsnd_process_addin_args(rdpsnd, args);
@ -732,24 +740,211 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin)
}
}
static void rdpsnd_process_event(rdpSvcPlugin* plugin, wMessage* event)
/****************************************************************************************/
static wListDictionary* g_InitHandles;
static wListDictionary* g_OpenHandles;
void rdpsnd_add_init_handle_data(void* pInitHandle, void* pUserData)
{
freerdp_event_free(event);
if (!g_InitHandles)
g_InitHandles = ListDictionary_New(TRUE);
ListDictionary_Add(g_InitHandles, pInitHandle, pUserData);
}
static void rdpsnd_process_terminate(rdpSvcPlugin* plugin)
void* rdpsnd_get_init_handle_data(void* pInitHandle)
{
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin;
void* pUserData = NULL;
pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
return pUserData;
}
void rdpsnd_remove_init_handle_data(void* pInitHandle)
{
ListDictionary_Remove(g_InitHandles, pInitHandle);
}
void rdpsnd_add_open_handle_data(DWORD openHandle, void* pUserData)
{
void* pOpenHandle = (void*) (size_t) openHandle;
if (!g_OpenHandles)
g_OpenHandles = ListDictionary_New(TRUE);
ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData);
}
void* rdpsnd_get_open_handle_data(DWORD openHandle)
{
void* pUserData = NULL;
void* pOpenHandle = (void*) (size_t) openHandle;
pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
return pUserData;
}
void rdpsnd_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
}
int rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s)
{
UINT32 status = 0;
if (!rdpsnd)
status = CHANNEL_RC_BAD_INIT_HANDLE;
else
status = rdpsnd->channelEntryPoints.pVirtualChannelWrite(rdpsnd->OpenHandle,
Stream_Buffer(s), Stream_GetPosition(s), s);
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
fprintf(stderr, "rdpdr_virtual_channel_write: VirtualChannelWrite failed %d\n", status);
}
return status;
}
static void rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
wStream* s;
if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
{
return;
}
if (dataFlags & CHANNEL_FLAG_FIRST)
{
if (plugin->data_in != NULL)
Stream_Free(plugin->data_in, TRUE);
plugin->data_in = Stream_New(NULL, totalLength);
}
s = plugin->data_in;
Stream_EnsureRemainingCapacity(s, (int) dataLength);
Stream_Write(s, pData, dataLength);
if (dataFlags & CHANNEL_FLAG_LAST)
{
if (Stream_Capacity(s) != Stream_GetPosition(s))
{
fprintf(stderr, "rdpsnd_virtual_channel_event_data_received: read error\n");
}
plugin->data_in = NULL;
Stream_SealLength(s);
Stream_SetPosition(s, 0);
MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) s, NULL);
}
}
static void rdpsnd_virtual_channel_open_event(UINT32 openHandle, UINT32 event,
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
rdpsndPlugin* plugin;
plugin = (rdpsndPlugin*) rdpsnd_get_open_handle_data(openHandle);
if (!plugin)
{
fprintf(stderr, "rdpsnd_virtual_channel_open_event: error no match\n");
return;
}
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
rdpsnd_virtual_channel_event_data_received(plugin, pData, dataLength, totalLength, dataFlags);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
Stream_Free((wStream*) pData, TRUE);
break;
case CHANNEL_EVENT_USER:
break;
}
}
static void* rdpsnd_virtual_channel_client_thread(void* arg)
{
wStream* data;
wMessage message;
rdpsndPlugin* plugin = (rdpsndPlugin*) arg;
rdpsnd_process_connect(plugin);
while (1)
{
if (!MessageQueue_Wait(plugin->MsgPipe->In))
break;
if (MessageQueue_Peek(plugin->MsgPipe->In, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
if (message.id == 0)
{
data = (wStream*) message.wParam;
rdpsnd_recv_pdu(plugin, data);
}
}
}
ExitThread(0);
return NULL;
}
static void rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, void* pData, UINT32 dataLength)
{
UINT32 status;
status = plugin->channelEntryPoints.pVirtualChannelOpen(plugin->InitHandle,
&plugin->OpenHandle, plugin->channelDef.name, rdpsnd_virtual_channel_open_event);
rdpsnd_add_open_handle_data(plugin->OpenHandle, plugin);
if (status != CHANNEL_RC_OK)
{
fprintf(stderr, "rdpsnd_virtual_channel_event_connected: open failed: status: %d\n", status);
return;
}
plugin->MsgPipe = MessagePipe_New();
plugin->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) plugin, 0, NULL);
}
static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
{
MessagePipe_PostQuit(rdpsnd->MsgPipe, 0);
WaitForSingleObject(rdpsnd->thread, INFINITE);
MessagePipe_Free(rdpsnd->MsgPipe);
CloseHandle(rdpsnd->thread);
rdpsnd->channelEntryPoints.pVirtualChannelClose(rdpsnd->OpenHandle);
if (rdpsnd->data_in)
{
Stream_Free(rdpsnd->data_in, TRUE);
rdpsnd->data_in = NULL;
}
if (rdpsnd->device)
IFCALL(rdpsnd->device->Free, rdpsnd->device);
MessageQueue_PostQuit(rdpsnd->queue, 0);
WaitForSingleObject(rdpsnd->thread, INFINITE);
MessageQueue_Free(rdpsnd->queue);
CloseHandle(rdpsnd->thread);
if (rdpsnd->subsystem)
free(rdpsnd->subsystem);
@ -763,6 +958,36 @@ static void rdpsnd_process_terminate(rdpSvcPlugin* plugin)
rdpsnd_free_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats);
rdpsnd->NumberOfClientFormats = 0;
rdpsnd->ClientFormats = NULL;
rdpsnd_remove_open_handle_data(rdpsnd->OpenHandle);
rdpsnd_remove_init_handle_data(rdpsnd->InitHandle);
}
static void rdpsnd_virtual_channel_init_event(void* pInitHandle, UINT32 event, void* pData, UINT32 dataLength)
{
rdpsndPlugin* plugin;
plugin = (rdpsndPlugin*) rdpsnd_get_init_handle_data(pInitHandle);
if (!plugin)
{
fprintf(stderr, "rdpsnd_virtual_channel_init_event: error no match\n");
return;
}
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
rdpsnd_virtual_channel_event_connected(plugin, pData, dataLength);
break;
case CHANNEL_EVENT_DISCONNECTED:
break;
case CHANNEL_EVENT_TERMINATED:
rdpsnd_virtual_channel_event_terminated(plugin);
break;
}
}
/* rdpsnd is always built-in */
@ -770,32 +995,36 @@ static void rdpsnd_process_terminate(rdpSvcPlugin* plugin)
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
rdpsndPlugin* _p;
rdpsndPlugin* rdpsnd;
_p = (rdpsndPlugin*) malloc(sizeof(rdpsndPlugin));
ZeroMemory(_p, sizeof(rdpsndPlugin));
rdpsnd = (rdpsndPlugin*) malloc(sizeof(rdpsndPlugin));
_p->plugin.channel_def.options =
CHANNEL_OPTION_INITIALIZED |
CHANNEL_OPTION_ENCRYPT_RDP;
strcpy(_p->plugin.channel_def.name, "rdpsnd");
_p->plugin.connect_callback = rdpsnd_process_connect;
_p->plugin.receive_callback = rdpsnd_recv_pdu;
_p->plugin.event_callback = rdpsnd_process_event;
_p->plugin.terminate_callback = rdpsnd_process_terminate;
if (rdpsnd)
{
ZeroMemory(rdpsnd, sizeof(rdpsndPlugin));
#if !defined(_WIN32) && !defined(ANDROID)
{
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGIO);
pthread_sigmask(SIG_BLOCK, &mask, NULL);
}
{
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGIO);
pthread_sigmask(SIG_BLOCK, &mask, NULL);
}
#endif
svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints);
rdpsnd->channelDef.options =
CHANNEL_OPTION_INITIALIZED |
CHANNEL_OPTION_ENCRYPT_RDP;
strcpy(rdpsnd->channelDef.name, "rdpsnd");
CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, pEntryPoints->cbSize);
rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle,
&rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpsnd_virtual_channel_init_event);
rdpsnd_add_init_handle_data(rdpsnd->InitHandle, (void*) rdpsnd);
}
return 1;
}

View File

@ -3,6 +3,7 @@
* Audio Output Virtual Channel
*
* Copyright 2010-2011 Vic Lee
* Copyright 2012-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.
@ -20,7 +21,10 @@
#ifndef __RDPSND_MAIN_H
#define __RDPSND_MAIN_H
#include <freerdp/channels/rdpsnd.h>
#include <freerdp/api.h>
#include <freerdp/svc.h>
#include <freerdp/addin.h>
#include <freerdp/client/rdpsnd.h>
#if defined(WITH_DEBUG_SND)
#define DEBUG_SND(fmt, ...) DEBUG_CLASS("rdpsnd", fmt, ## __VA_ARGS__)
@ -28,75 +32,6 @@
#define DEBUG_SND(fmt, ...) do { } while (0)
#endif
struct _RDPSND_WAVE
{
BYTE* data;
int length;
BYTE cBlockNo;
UINT16 wFormatNo;
UINT16 wTimeStampA;
UINT16 wTimeStampB;
UINT16 wLatency;
UINT16 wAudioLength;
UINT16 wPlaybackDelay;
UINT32 wLocalTimeA;
UINT32 wLocalTimeB;
};
typedef struct _RDPSND_WAVE RDPSND_WAVE;
typedef struct rdpsnd_plugin rdpsndPlugin;
typedef struct rdpsnd_device_plugin rdpsndDevicePlugin;
typedef BOOL (*pcFormatSupported) (rdpsndDevicePlugin* device, AUDIO_FORMAT* format);
typedef void (*pcOpen) (rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency);
typedef void (*pcSetFormat) (rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency);
typedef UINT32 (*pcGetVolume) (rdpsndDevicePlugin* device);
typedef void (*pcSetVolume) (rdpsndDevicePlugin* device, UINT32 value);
typedef void (*pcPlay) (rdpsndDevicePlugin* device, BYTE* data, int size);
typedef void (*pcStart) (rdpsndDevicePlugin* device);
typedef void (*pcClose) (rdpsndDevicePlugin* device);
typedef void (*pcFree) (rdpsndDevicePlugin* device);
typedef void (*pcWaveDecode) (rdpsndDevicePlugin* device, RDPSND_WAVE* wave);
typedef void (*pcWavePlay) (rdpsndDevicePlugin* device, RDPSND_WAVE* wave);
typedef void (*pcWaveConfirm) (rdpsndDevicePlugin* device, RDPSND_WAVE* wave);
struct rdpsnd_device_plugin
{
rdpsndPlugin* rdpsnd;
pcFormatSupported FormatSupported;
pcOpen Open;
pcSetFormat SetFormat;
pcGetVolume GetVolume;
pcSetVolume SetVolume;
pcPlay Play;
pcStart Start;
pcClose Close;
pcFree Free;
pcWaveDecode WaveDecode;
pcWavePlay WavePlay;
pcWaveConfirm WaveConfirm;
};
#define RDPSND_DEVICE_EXPORT_FUNC_NAME "freerdp_rdpsnd_client_subsystem_entry"
typedef void (*PREGISTERRDPSNDDEVICE)(rdpsndPlugin* rdpsnd, rdpsndDevicePlugin* device);
struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS
{
rdpsndPlugin* rdpsnd;
PREGISTERRDPSNDDEVICE pRegisterRdpsndDevice;
ADDIN_ARGV* args;
};
typedef struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS FREERDP_RDPSND_DEVICE_ENTRY_POINTS;
typedef FREERDP_RDPSND_DEVICE_ENTRY_POINTS* PFREERDP_RDPSND_DEVICE_ENTRY_POINTS;
typedef int (*PFREERDP_RDPSND_DEVICE_ENTRY)(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints);
int rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s);
#endif /* __RDPSND_MAIN_H */

View File

@ -40,8 +40,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winmm.lib)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/WinMM")

View File

@ -32,4 +32,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -30,8 +30,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MODULE freerdp
MODULES freerdp-utils)
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -34,9 +34,6 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -47,12 +47,13 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <freerdp/freerdp.h>
#include <freerdp/utils/list.h>
#include <winpr/stream.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/utils/svc_plugin.h>
typedef struct _SERIAL_DEVICE SERIAL_DEVICE;

View File

@ -42,9 +42,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PCSC_LIBRARIES})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -31,7 +31,6 @@
#include <freerdp/utils/list.h>
#include <freerdp/utils/debug.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/channels/rdpdr.h>
@ -229,7 +228,7 @@ static void smartcard_irp_complete(IRP* irp)
* to be in this file so that "smartcard_irp_request()" can reference it.
*/
DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId);
DEBUG_SCARD("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId);
pos = Stream_GetPosition(irp->output);
Stream_SetPosition(irp->output, 12);
@ -246,8 +245,7 @@ static void smartcard_irp_complete(IRP* irp)
if (!duplicate)
{
svc_plugin_send(irp->devman->plugin, irp->output);
irp->output = NULL;
irp->Complete(irp);
}
/* End TS Client defect workaround. */

View File

@ -47,9 +47,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -36,6 +36,4 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ALSA_LIBRARIES})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)

View File

@ -31,20 +31,17 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-utils)
if(APPLE)
# For this to work on apple, we need to add some frameworks
FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation )
FIND_LIBRARY(COREVIDEO_LIBRARY CoreVideo )
FIND_LIBRARY(COREVIDEODECODE_LIBRARY VideoDecodeAcceleration )
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${FFMPEG_LIBRARIES} ${COREFOUNDATION_LIBRARY} ${COREVIDEO_LIBRARY} ${COREVIDEODECODE_LIBRARY} )
FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation)
FIND_LIBRARY(COREVIDEO_LIBRARY CoreVideo)
FIND_LIBRARY(COREVIDEODECODE_LIBRARY VideoDecodeAcceleration)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${FFMPEG_LIBRARIES} ${COREFOUNDATION_LIBRARY} ${COREVIDEO_LIBRARY} ${COREVIDEODECODE_LIBRARY})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
else()
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${FFMPEG_LIBRARIES})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
endif()
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)

View File

@ -40,6 +40,4 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)

View File

@ -36,7 +36,4 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)

View File

@ -58,9 +58,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(NOT STATIC_CHANNELS)
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
endif()
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -464,7 +464,7 @@ int main(int argc, char* argv[])
instance->context->argc = argc;
instance->context->argv = argv;
status = freerdp_client_parse_command_line_arguments(argc, argv, instance->settings);
status = freerdp_client_settings_parse_command_line(instance->settings, argc, argv);
if (status < 0)
exit(0);

View File

@ -41,43 +41,27 @@
@interface MRDPView : NSView
{
mfContext* mfc;
NSBitmapImageRep* bmiRep;
NSMutableArray* cursors;
NSMutableArray* windows;
NSTimer* pasteboard_timer;
NSCursor* currentCursor;
NSCursor* currentCursor;
NSRect prevWinPosition;
int titleBarHeight;
freerdp* instance;
rdpContext* context;
CGContextRef bitmap_context;
char* pixel_data;
int width;
int height;
int argc;
char** argv;
DWORD kbdModFlags;
BOOL initialized;
NSPoint savedDragLocation;
BOOL firstCreateWindow;
BOOL isMoveSizeInProgress;
BOOL skipResizeOnce;
BOOL saveInitialDragLoc;
BOOL skipMoveWindowOnce;
/* store state info for some keys */
int kdlshift;
int kdrshift;
int kdlctrl;
int kdrctrl;
int kdlalt;
int kdralt;
int kdlmeta;
int kdrmeta;
int kdcapslock;
BOOL initialized;
NSImageView* imageView;
@public
NSPasteboard* pasteboard_rd; /* for reading from clipboard */
@ -89,10 +73,10 @@
- (int) rdpStart :(rdpContext*) rdp_context;
- (void) setCursor: (NSCursor*) cursor;
- (void) setScrollOffset:(int)xOffset y:(int)yOffset w:(int)width h:(int)height;
- (void) onPasteboardTimerFired :(NSTimer *) timer;
- (void) releaseResources;
- (void) setViewSize : (int) w : (int) h;
@property (assign) int is_connected;

View File

@ -123,11 +123,10 @@ struct rgba_data
- (int) rdpStart:(rdpContext*) rdp_context
{
mfContext* mfc;
rdpSettings* settings;
EmbedWindowEventArgs e;
[self initializeView];
[self initializeView];
context = rdp_context;
mfc = (mfContext*) rdp_context;
@ -148,13 +147,10 @@ struct rgba_data
instance->settings->DesktopHeight = screenFrame.size.height;
}
[self setViewSize :instance->settings->DesktopWidth :instance->settings->DesktopHeight];
mfc->client_height = instance->settings->DesktopHeight;
mfc->client_width = instance->settings->DesktopWidth;
if(instance->settings->Fullscreen)
[[self window] toggleFullScreen:nil];
mfc->thread = CreateThread(NULL, 0, mac_client_thread, (void*) context, 0, &mfc->mainThreadId);
mfc->thread = CreateThread(NULL, 0, mac_client_thread, (void*) context, 0, &mfc->mainThreadId);
return 0;
}
@ -174,6 +170,7 @@ DWORD mac_client_thread(void* param)
mfContext* mfc = (mfContext*) context;
freerdp* instance = context->instance;
MRDPView* view = mfc->view;
rdpSettings* settings = context->settings;
status = freerdp_connect(context->instance);
@ -189,17 +186,17 @@ DWORD mac_client_thread(void* param)
events[nCount++] = mfc->stopEvent;
if (instance->settings->AsyncUpdate)
if (settings->AsyncUpdate)
{
events[nCount++] = update_event = freerdp_get_message_queue_event_handle(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
}
if (instance->settings->AsyncInput)
if (settings->AsyncInput)
{
events[nCount++] = input_event = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
}
if (instance->settings->AsyncChannels)
if (settings->AsyncChannels)
{
events[nCount++] = channels_event = freerdp_channels_get_event_handle(instance);
}
@ -210,10 +207,11 @@ DWORD mac_client_thread(void* param)
if (WaitForSingleObject(mfc->stopEvent, 0) == WAIT_OBJECT_0)
{
freerdp_disconnect(instance);
break;
}
if (instance->settings->AsyncUpdate)
if (settings->AsyncUpdate)
{
if (WaitForSingleObject(update_event, 0) == WAIT_OBJECT_0)
{
@ -221,7 +219,7 @@ DWORD mac_client_thread(void* param)
}
}
if (instance->settings->AsyncInput)
if (settings->AsyncInput)
{
if (WaitForSingleObject(input_event, 0) == WAIT_OBJECT_0)
{
@ -229,7 +227,7 @@ DWORD mac_client_thread(void* param)
}
}
if (instance->settings->AsyncChannels)
if (settings->AsyncChannels)
{
if (WaitForSingleObject(channels_event, 0) == WAIT_OBJECT_0)
{
@ -253,7 +251,7 @@ DWORD mac_client_thread(void* param)
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
self = [super initWithFrame:frame];
if (self)
{
@ -271,48 +269,38 @@ DWORD mac_client_thread(void* param)
// won't be called if the view is created dynamically
- (void) viewDidLoad
{
[self initializeView];
[self initializeView];
}
- (void) initializeView
{
if (!initialized)
{
// store our window dimensions
width = [self frame].size.width;
height = [self frame].size.height;
titleBarHeight = 22;
if (!initialized)
{
cursors = [[NSMutableArray alloc] initWithCapacity:10];
[[self window] becomeFirstResponder];
[[self window] setAcceptsMouseMovedEvents:YES];
// setup a mouse tracking area
NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil];
cursors = [[NSMutableArray alloc] initWithCapacity:10];
[self addTrackingArea:trackingArea];
// setup a mouse tracking area
NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil];
// Set the default cursor
currentCursor = [NSCursor arrowCursor];
[self addTrackingArea:trackingArea];
// Set the default cursor
currentCursor = [NSCursor arrowCursor];
initialized = YES;
}
initialized = YES;
}
}
- (void) setCursor: (NSCursor*) cursor
{
self->currentCursor = cursor;
[[self window] invalidateCursorRectsForView:self];
[imageView setImage:[currentCursor image]];
self->currentCursor = cursor;
[[self window] invalidateCursorRectsForView:self];
}
// Set the current cursor
- (void) resetCursorRects
{
[self addCursorRect:[self visibleRect] cursor:currentCursor];
[self addCursorRect:[self visibleRect] cursor:currentCursor];
}
/** *********************************************************************
@ -347,11 +335,8 @@ DWORD mac_client_thread(void* param)
NSPoint loc = [event locationInWindow];
int x = (int) loc.x;
int y = (int) loc.y;
y = height - y;
// send mouse motion event to RDP server
instance->input->MouseEvent(instance->input, PTR_FLAGS_MOVE, x, y);
mf_scale_mouse_event(context, instance->input, PTR_FLAGS_MOVE, x, y);
}
/** *********************************************************************
@ -369,9 +354,7 @@ DWORD mac_client_thread(void* param)
int x = (int) loc.x;
int y = (int) loc.y;
y = height - y;
instance->input->MouseEvent(instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, x, y);
mf_scale_mouse_event(context, instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, x, y);
}
/** *********************************************************************
@ -389,9 +372,7 @@ DWORD mac_client_thread(void* param)
int x = (int) loc.x;
int y = (int) loc.y;
y = height - y;
instance->input->MouseEvent(instance->input, PTR_FLAGS_BUTTON1, x, y);
mf_scale_mouse_event(context, instance->input, PTR_FLAGS_BUTTON1, x, y);
}
/** *********************************************************************
@ -409,9 +390,7 @@ DWORD mac_client_thread(void* param)
int x = (int) loc.x;
int y = (int) loc.y;
y = height - y;
instance->input->MouseEvent(instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, x, y);
mf_scale_mouse_event(context, instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, x, y);
}
/** *********************************************************************
@ -429,9 +408,7 @@ DWORD mac_client_thread(void* param)
int x = (int) loc.x;
int y = (int) loc.y;
y = height - y;
instance->input->MouseEvent(instance->input, PTR_FLAGS_BUTTON2, x, y);
mf_scale_mouse_event(context, instance->input, PTR_FLAGS_BUTTON2, x, y);
}
/** *********************************************************************
@ -449,9 +426,7 @@ DWORD mac_client_thread(void* param)
int x = (int) loc.x;
int y = (int) loc.y;
y = height - y;
instance->input->MouseEvent(instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3, x, y);
mf_scale_mouse_event(context, instance->input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3, x, y);
}
/** *********************************************************************
@ -469,9 +444,7 @@ DWORD mac_client_thread(void* param)
int x = (int) loc.x;
int y = (int) loc.y;
y = height - y;
instance->input->MouseEvent(instance->input, PTR_FLAGS_BUTTON3, x, y);
mf_scale_mouse_event(context, instance->input, PTR_FLAGS_BUTTON3, x, y);
}
- (void) scrollWheel:(NSEvent *)event
@ -486,8 +459,6 @@ DWORD mac_client_thread(void* param)
NSPoint loc = [event locationInWindow];
int x = (int) loc.x;
int y = (int) loc.y;
y = height - y;
flags = PTR_FLAGS_WHEEL;
@ -500,7 +471,7 @@ DWORD mac_client_thread(void* param)
/* limit to maximum value in WheelRotationMask (9bit signed value) */
int step = MIN(MAX(-256, units), 255);
instance->input->MouseEvent(instance->input, flags | ((UINT16)step & WheelRotationMask), x, y);
mf_scale_mouse_event(context, instance->input, flags | ((UINT16)step & WheelRotationMask), x, y);
units -= step;
}
}
@ -521,10 +492,8 @@ DWORD mac_client_thread(void* param)
int x = (int) loc.x;
int y = (int) loc.y;
y = height - y;
// send mouse motion event to RDP server
instance->input->MouseEvent(instance->input, PTR_FLAGS_MOVE, x, y);
mf_scale_mouse_event(context, instance->input, PTR_FLAGS_MOVE, x, y);
}
/** *********************************************************************
@ -534,20 +503,28 @@ DWORD mac_client_thread(void* param)
- (void) keyDown:(NSEvent *) event
{
int key;
USHORT extended;
DWORD keyFlags;
DWORD vkcode;
DWORD scancode;
if (!is_connected)
return;
keyFlags = KBD_FLAGS_DOWN;
key = [event keyCode] + 8;
vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE);
scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
extended = (scancode & KBDEXT) ? KBDEXT : 0;
keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
scancode &= 0xFF;
vkcode &= 0xFF;
#if 0
fprintf(stderr, "keyDown: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s\n",
key - 8, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
#endif
instance->input->KeyboardEvent(instance->input, extended | KBD_FLAGS_DOWN, scancode & 0xFF);
freerdp_input_send_keyboard_event(instance->input, keyFlags, scancode);
}
/** *********************************************************************
@ -557,20 +534,28 @@ DWORD mac_client_thread(void* param)
- (void) keyUp:(NSEvent *) event
{
int key;
USHORT extended;
DWORD keyFlags;
DWORD vkcode;
DWORD scancode;
if (!is_connected)
return;
key = [event keyCode] + 8;
keyFlags = KBD_FLAGS_RELEASE;
vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE);
scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
extended = (scancode & KBDEXT) ? KBDEXT : 0;
instance->input->KeyboardEvent(instance->input, extended | KBD_FLAGS_RELEASE, scancode & 0xFF);
keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
scancode &= 0xFF;
vkcode &= 0xFF;
#if 0
fprintf(stderr, "keyUp: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s\n",
key - 8, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
#endif
freerdp_input_send_keyboard_event(instance->input, keyFlags, scancode);
}
/** *********************************************************************
@ -579,122 +564,93 @@ DWORD mac_client_thread(void* param)
- (void) flagsChanged:(NSEvent*) event
{
NSUInteger mf = [event modifierFlags];
int key;
DWORD keyFlags;
DWORD vkcode;
DWORD scancode;
DWORD modFlags;
if (!is_connected)
return;
// caps lock
if (mf == 0x10100) {
printf("TODO: caps lock is on\n");
kdcapslock = 1;
}
if (kdcapslock && (mf == 0x100)) {
kdcapslock = 0;
printf("TODO: caps lock is off\n");
}
// left shift
if ((kdlshift == 0) && ((mf & 2) != 0)) {
// left shift went down
instance->input->KeyboardEvent(instance->input, KBD_FLAGS_DOWN, 0x2a);
kdlshift = 1;
}
if ((kdlshift != 0) && ((mf & 2) == 0)) {
// left shift went up
instance->input->KeyboardEvent(instance->input, KBD_FLAGS_RELEASE, 0x2a);
kdlshift = 0;
}
// right shift
if ((kdrshift == 0) && ((mf & 4) != 0)) {
// right shift went down
instance->input->KeyboardEvent(instance->input, KBD_FLAGS_DOWN, 0x36);
kdrshift = 1;
}
if ((kdrshift != 0) && ((mf & 4) == 0)) {
// right shift went up
instance->input->KeyboardEvent(instance->input, KBD_FLAGS_RELEASE, 0x36);
kdrshift = 0;
}
// left ctrl
if ((kdlctrl == 0) && ((mf & 1) != 0)) {
// left ctrl went down
instance->input->KeyboardEvent(instance->input, KBD_FLAGS_DOWN, 0x1d);
kdlctrl = 1;
}
if ((kdlctrl != 0) && ((mf & 1) == 0)) {
// left ctrl went up
instance->input->KeyboardEvent(instance->input, KBD_FLAGS_RELEASE, 0x1d);
kdlctrl = 0;
}
// right ctrl
if ((kdrctrl == 0) && ((mf & 0x2000) != 0)) {
// right ctrl went down
instance->input->KeyboardEvent(instance->input, 1 | KBD_FLAGS_DOWN, 0x1d);
kdrctrl = 1;
}
if ((kdrctrl != 0) && ((mf & 0x2000) == 0)) {
// right ctrl went up
instance->input->KeyboardEvent(instance->input, 1 | KBD_FLAGS_RELEASE, 0x1d);
kdrctrl = 0;
}
// left alt
if ((kdlalt == 0) && ((mf & 0x20) != 0)) {
// left alt went down
instance->input->KeyboardEvent(instance->input, KBD_FLAGS_DOWN, 0x38);
kdlalt = 1;
}
if ((kdlalt != 0) && ((mf & 0x20) == 0)) {
// left alt went up
instance->input->KeyboardEvent(instance->input, KBD_FLAGS_RELEASE, 0x38);
kdlalt = 0;
}
// right alt
if ((kdralt == 0) && ((mf & 0x40) != 0)) {
// right alt went down
instance->input->KeyboardEvent(instance->input, 1 | KBD_FLAGS_DOWN, 0x38);
kdralt = 1;
}
if ((kdralt != 0) && ((mf & 0x40) == 0)) {
// right alt went up
instance->input->KeyboardEvent(instance->input, 1 | KBD_FLAGS_RELEASE, 0x38);
kdralt = 0;
}
// left meta
if ((kdlmeta == 0) && ((mf & 0x08) != 0)) {
// left meta went down
instance->input->KeyboardEvent(instance->input, 1 | KBD_FLAGS_DOWN, 0x5b);
kdlmeta = 1;
}
if ((kdlmeta != 0) && ((mf & 0x08) == 0)) {
// left meta went up
instance->input->KeyboardEvent(instance->input, 1 | KBD_FLAGS_RELEASE, 0x5b);
kdlmeta = 0;
}
// right meta
if ((kdrmeta == 0) && ((mf & 0x10) != 0)) {
// right meta went down
instance->input->KeyboardEvent(instance->input, 1 | KBD_FLAGS_DOWN, 0x5c);
kdrmeta = 1;
}
if ((kdrmeta != 0) && ((mf & 0x10) == 0)) {
// right meta went up
instance->input->KeyboardEvent(instance->input, 1 | KBD_FLAGS_RELEASE, 0x5c);
kdrmeta = 0;
}
keyFlags = 0;
key = [event keyCode] + 8;
modFlags = [event modifierFlags] & NSDeviceIndependentModifierFlagsMask;
vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE);
scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
scancode &= 0xFF;
vkcode &= 0xFF;
#if 0
fprintf(stderr, "flagsChanged: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X extended: %d name: %s modFlags: 0x%04X\n",
key - 8, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode), modFlags);
if (modFlags & NSAlphaShiftKeyMask)
fprintf(stderr, "NSAlphaShiftKeyMask\n");
if (modFlags & NSShiftKeyMask)
fprintf(stderr, "NSShiftKeyMask\n");
if (modFlags & NSControlKeyMask)
fprintf(stderr, "NSControlKeyMask\n");
if (modFlags & NSAlternateKeyMask)
fprintf(stderr, "NSAlternateKeyMask\n");
if (modFlags & NSCommandKeyMask)
fprintf(stderr, "NSCommandKeyMask\n");
if (modFlags & NSNumericPadKeyMask)
fprintf(stderr, "NSNumericPadKeyMask\n");
if (modFlags & NSHelpKeyMask)
fprintf(stderr, "NSHelpKeyMask\n");
#endif
if ((modFlags & NSAlphaShiftKeyMask) && !(kbdModFlags & NSAlphaShiftKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_DOWN, scancode);
else if (!(modFlags & NSAlphaShiftKeyMask) && (kbdModFlags & NSAlphaShiftKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_RELEASE, scancode);
if ((modFlags & NSShiftKeyMask) && !(kbdModFlags & NSShiftKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_DOWN, scancode);
else if (!(modFlags & NSShiftKeyMask) && (kbdModFlags & NSShiftKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_RELEASE, scancode);
if ((modFlags & NSControlKeyMask) && !(kbdModFlags & NSControlKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_DOWN, scancode);
else if (!(modFlags & NSControlKeyMask) && (kbdModFlags & NSControlKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_RELEASE, scancode);
if ((modFlags & NSAlternateKeyMask) && !(kbdModFlags & NSAlternateKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_DOWN, scancode);
else if (!(modFlags & NSAlternateKeyMask) && (kbdModFlags & NSAlternateKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_RELEASE, scancode);
if ((modFlags & NSCommandKeyMask) && !(kbdModFlags & NSCommandKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_DOWN, scancode);
else if (!(modFlags & NSCommandKeyMask) && (kbdModFlags & NSCommandKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_RELEASE, scancode);
if ((modFlags & NSNumericPadKeyMask) && !(kbdModFlags & NSNumericPadKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_DOWN, scancode);
else if (!(modFlags & NSNumericPadKeyMask) && (kbdModFlags & NSNumericPadKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_RELEASE, scancode);
if ((modFlags & NSHelpKeyMask) && !(kbdModFlags & NSHelpKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_DOWN, scancode);
else if (!(modFlags & NSHelpKeyMask) && (kbdModFlags & NSHelpKeyMask))
freerdp_input_send_keyboard_event(instance->input, keyFlags | KBD_FLAGS_RELEASE, scancode);
kbdModFlags = modFlags;
}
- (void) releaseResources
{
int i;
for (i = 0; i < argc; i++)
{
if (argv[i])
@ -725,14 +681,15 @@ DWORD mac_client_thread(void* param)
CGImageRef cgImage = CGBitmapContextCreateImage(self->bitmap_context);
CGContextClipToRect(cgContext, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height));
CGContextDrawImage(cgContext, CGRectMake(0, 0, [self bounds].size.width, [self bounds].size.height), cgImage);
CGContextDrawImage(cgContext, CGRectMake(0,
0, [self bounds].size.width, [self bounds].size.height), cgImage);
CGImageRelease(cgImage);
}
else
{
// just clear the screen with black
[[NSColor redColor] set];
[[NSColor blackColor] set];
NSRectFill([self bounds]);
}
}
@ -760,30 +717,12 @@ DWORD mac_client_thread(void* param)
}
}
- (void) setViewSize : (int) w : (int) h
- (void) setScrollOffset:(int)xOffset y:(int)yOffset w:(int)width h:(int)height
{
// store current dimensions
width = w;
height = h;
// set client area to specified dimensions
NSRect innerRect;
innerRect.origin.x = 0;
innerRect.origin.y = 0;
innerRect.size.width = w;
innerRect.size.height = h;
[self setFrame:innerRect];
// calculate window of same size, but keep position
NSRect outerRect = [[self window] frame];
outerRect.size = [[self window] frameRectForContentRect:innerRect].size;
// we are not in RemoteApp mode, disable larger than resolution
[[self window] setContentMaxSize:innerRect.size];
// set window to given area
[[self window] setFrame:outerRect display:YES];
mfc->yCurrentScroll = yOffset;
mfc->xCurrentScroll = xOffset;
mfc->client_height = height;
mfc->client_width = width;
}
/************************************************************************
@ -974,11 +913,11 @@ void mf_Pointer_New(rdpContext* context, rdpPointer* pointer)
cursor_data = (BYTE*) malloc(rect.size.width * rect.size.height * 4);
mrdpCursor->cursor_data = cursor_data;
if (pointer->xorBpp > 24)
{
freerdp_image_swap_color_order(pointer->xorMaskData, pointer->width, pointer->height);
if (pointer->xorBpp > 24)
{
freerdp_image_swap_color_order(pointer->xorMaskData, pointer->width, pointer->height);
}
freerdp_alpha_cursor_convert(cursor_data, pointer->xorMaskData, pointer->andMaskData,
pointer->width, pointer->height, pointer->xorBpp, context->gdi->clrconv);
@ -1057,12 +996,12 @@ void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer)
{
if (cursor->pointer == pointer)
{
[view setCursor:cursor->nsCursor];
[view setCursor:cursor->nsCursor];
return;
}
}
NSLog(@"Cursor not found");
NSLog(@"Cursor not found");
}
/** *********************************************************************
@ -1082,7 +1021,7 @@ void mf_Pointer_SetDefault(rdpContext* context)
{
mfContext* mfc = (mfContext*) context;
MRDPView* view = (MRDPView*) mfc->view;
[view setCursor:[NSCursor arrowCursor]];
[view setCursor:[NSCursor arrowCursor]];
}
/** *********************************************************************
@ -1125,6 +1064,13 @@ void mac_end_paint(rdpContext* context)
mfContext* mfc = (mfContext*) context;
MRDPView* view = (MRDPView*) mfc->view;
int ww, wh, dw, dh;
ww = mfc->client_width;
wh = mfc->client_height;
dw = mfc->context.settings->DesktopWidth;
dh = mfc->context.settings->DesktopHeight;
if ((context == 0) || (context->gdi == 0))
return;
@ -1138,11 +1084,31 @@ void mac_end_paint(rdpContext* context)
for (i = 0; i < gdi->primary->hdc->hwnd->ninvalid; i++)
{
drawRect.origin.x = gdi->primary->hdc->hwnd->cinvalid[i].x - 1;
drawRect.origin.y = gdi->primary->hdc->hwnd->cinvalid[i].y - 1;
drawRect.size.width = gdi->primary->hdc->hwnd->cinvalid[i].w + 1;
drawRect.size.height = gdi->primary->hdc->hwnd->cinvalid[i].h + 1;
drawRect.origin.x = gdi->primary->hdc->hwnd->cinvalid[i].x;
drawRect.origin.y = gdi->primary->hdc->hwnd->cinvalid[i].y;
drawRect.size.width = gdi->primary->hdc->hwnd->cinvalid[i].w;
drawRect.size.height = gdi->primary->hdc->hwnd->cinvalid[i].h;
if (mfc->context.settings->SmartSizing && (ww != dw || wh != dh))
{
drawRect.origin.y = drawRect.origin.y * wh / dh - 1;
drawRect.size.height = drawRect.size.height * wh / dh + 1;
drawRect.origin.x = drawRect.origin.x * ww / dw - 1;
drawRect.size.width = drawRect.size.width * ww / dw + 1;
}
else
{
drawRect.origin.y = drawRect.origin.y - 1;
drawRect.size.height = drawRect.size.height + 1;
drawRect.origin.x = drawRect.origin.x - 1;
drawRect.size.width = drawRect.size.width + 1;
}
windows_to_apple_cords(mfc->view, &drawRect);
// Note: The xCurrentScroll and yCurrentScroll values do not need to be taken into account
// because the current frame is always at full size, since the scrolling is handled by the external container.
[view setNeedsDisplayInRect:drawRect];
}
@ -1175,7 +1141,7 @@ static void update_activity_cb(freerdp* instance)
}
else
{
fprintf(stderr, "update_activity_cb: No queue!\n");
fprintf(stderr, "update_activity_cb: No queue!\n");
}
}
@ -1187,7 +1153,7 @@ static void input_activity_cb(freerdp* instance)
{
int status;
wMessage message;
wMessageQueue* queue;
wMessageQueue* queue;
status = 1;
queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
@ -1202,10 +1168,10 @@ static void input_activity_cb(freerdp* instance)
break;
}
}
else
{
fprintf(stderr, "input_activity_cb: No queue!\n");
}
else
{
fprintf(stderr, "input_activity_cb: No queue!\n");
}
}
/** *********************************************************************
@ -1214,14 +1180,16 @@ static void input_activity_cb(freerdp* instance)
static void channel_activity_cb(freerdp* instance)
{
wMessage* event;
wMessage* event;
freerdp_channels_process_pending_messages(instance);
event = freerdp_channels_pop_event(instance->context->channels);
if (event)
{
fprintf(stderr, "channel_activity_cb: message %d\n", event->id);
switch (GetMessageClass(event->id))
fprintf(stderr, "channel_activity_cb: message %d\n", event->id);
switch (GetMessageClass(event->id))
{
case CliprdrChannel_Class:
process_cliprdr_event(instance, event);
@ -1477,7 +1445,8 @@ void cliprdr_send_supported_format_list(freerdp* instance)
void windows_to_apple_cords(MRDPView* view, NSRect* r)
{
r->origin.y = view->height - (r->origin.y + r->size.height);
r->origin.y = [view frame].size.height - (r->origin.y + r->size.height);
}
@end

View File

@ -9,12 +9,15 @@
#import "AppDelegate.h"
#import "MacFreeRDP/mfreerdp.h"
#import "MacFreeRDP/mf_client.h"
#import "MacFreeRDP/MRDPView.h"
#import <freerdp/client/cmdline.h>
static AppDelegate* _singleDelegate = nil;
void AppDelegate_EmbedWindowEventHandler(void* context, EmbedWindowEventArgs* e);
void AppDelegate_ConnectionResultEventHandler(void* context, ConnectionResultEventArgs* e);
void AppDelegate_ErrorInfoEventHandler(void* ctx, ErrorInfoEventArgs* e);
int mac_client_start(rdpContext* context);
void mac_set_view_size(rdpContext* context, MRDPView* view);
@implementation AppDelegate
@ -33,7 +36,7 @@ void AppDelegate_ErrorInfoEventHandler(void* ctx, ErrorInfoEventArgs* e);
int status;
mfContext* mfc;
_singleDelegate = self;
_singleDelegate = self;
[self CreateContext];
status = [self ParseCommandLineArguments];
@ -90,8 +93,8 @@ void AppDelegate_ErrorInfoEventHandler(void* ctx, ErrorInfoEventArgs* e);
argv[i++] = cptr;
}
status = freerdp_client_parse_command_line(context, argc, argv);
status = freerdp_client_command_line_status_print(context->argc, context->argv, context->settings, status);
status = freerdp_client_settings_parse_command_line(context->settings, argc, argv);
status = freerdp_client_settings_command_line_status_print(context->settings, status, context->argc, context->argv);
return status;
}
@ -105,12 +108,24 @@ void AppDelegate_ErrorInfoEventHandler(void* ctx, ErrorInfoEventArgs* e);
clientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
RdpClientEntry(&clientEntryPoints);
clientEntryPoints.ClientStart = mac_client_start;
context = freerdp_client_context_new(&clientEntryPoints);
}
- (void) ReleaseContext
{
mfContext* mfc;
MRDPView* view;
mfc = (mfContext*) context;
view = (MRDPView*) mfc->view;
[view releaseResources];
[view release];
mfc->view = nil;
freerdp_client_context_free(context);
context = nil;
}
@ -158,6 +173,9 @@ void AppDelegate_EmbedWindowEventHandler(void* ctx, EmbedWindowEventArgs* e)
{
[[_singleDelegate->window contentView] addSubview:mfc->view];
}
mac_set_view_size(context, mfc->view);
}
}
@ -203,4 +221,45 @@ void AppDelegate_ErrorInfoEventHandler(void* ctx, ErrorInfoEventArgs* e)
[_singleDelegate performSelectorOnMainThread:@selector(rdpConnectError:) withObject:message waitUntilDone:TRUE];
[message release];
}
}
}
void mac_set_view_size(rdpContext* context, MRDPView* view)
{
// set client area to specified dimensions
NSRect innerRect;
innerRect.origin.x = 0;
innerRect.origin.y = 0;
innerRect.size.width = context->settings->DesktopWidth;
innerRect.size.height = context->settings->DesktopHeight;
[view setFrame:innerRect];
// calculate window of same size, but keep position
NSRect outerRect = [[view window] frame];
outerRect.size = [[view window] frameRectForContentRect:innerRect].size;
// we are not in RemoteApp mode, disable larger than resolution
[[view window] setContentMaxSize:innerRect.size];
// set window to given area
[[view window] setFrame:outerRect display:YES];
if(context->settings->Fullscreen)
[[view window] toggleFullScreen:nil];
}
int mac_client_start(rdpContext* context)
{
mfContext* mfc;
MRDPView* view;
mfc = (mfContext*) context;
view = [[MRDPView alloc] initWithFrame : NSMakeRect(0, 0, context->settings->DesktopWidth, context->settings->DesktopHeight)];
mfc->view = view;
[view rdpStart:context];
mac_set_view_size(context, view);
return 0;
}

View File

@ -28,6 +28,8 @@
extern "C" {
#endif
FREERDP_API void mf_scale_mouse_event(void* context, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y);
/**
* Client Interface
*/

View File

@ -25,7 +25,6 @@
#include <freerdp/constants.h>
#include <freerdp/utils/signal.h>
#include <freerdp/client/cmdline.h>
#import "MRDPView.h"
/**
* Client Interface
@ -47,12 +46,12 @@ int mfreerdp_client_start(rdpContext* context)
MRDPView* view;
mfContext* mfc = (mfContext*) context;
if (mfc->view == NULL)
{
// view not specified beforehand. Create view dynamically
mfc->view = [[MRDPView alloc] initWithFrame : NSMakeRect(0, 0, context->settings->DesktopWidth, context->settings->DesktopHeight)];
mfc->view_ownership = TRUE;
}
if (mfc->view == NULL)
{
// view not specified beforehand. Create view dynamically
mfc->view = [[MRDPView alloc] initWithFrame : NSMakeRect(0, 0, context->settings->DesktopWidth, context->settings->DesktopHeight)];
mfc->view_ownership = TRUE;
}
view = (MRDPView*) mfc->view;
[view rdpStart:context];
@ -63,45 +62,22 @@ int mfreerdp_client_start(rdpContext* context)
int mfreerdp_client_stop(rdpContext* context)
{
mfContext* mfc = (mfContext*) context;
if (context->settings->AsyncUpdate)
if (mfc->thread)
{
wMessageQueue* queue;
queue = freerdp_get_message_queue(context->instance, FREERDP_UPDATE_MESSAGE_QUEUE);
if (queue)
{
MessageQueue_PostQuit(queue, 0);
}
}
else if (context->settings->AsyncInput)
{
wMessageQueue* queue;
queue = freerdp_get_message_queue(context->instance, FREERDP_INPUT_MESSAGE_QUEUE);
if (queue)
{
MessageQueue_PostQuit(queue, 0);
}
}
else
{
mfc->disconnect = TRUE;
SetEvent(mfc->stopEvent);
WaitForSingleObject(mfc->thread, INFINITE);
CloseHandle(mfc->thread);
mfc->thread = NULL;
}
if (mfc->thread)
{
SetEvent(mfc->stopEvent);
WaitForSingleObject(mfc->thread, INFINITE);
CloseHandle(mfc->thread);
mfc->thread = NULL;
}
if (mfc->view_ownership)
{
MRDPView* view = (MRDPView*) mfc->view;
[view releaseResources];
[view release];
mfc->view = nil;
}
if (mfc->view_ownership)
{
MRDPView* view = (MRDPView*) mfc->view;
[view releaseResources];
[view release];
mfc->view = nil;
}
return 0;
}
@ -113,22 +89,21 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context)
mfc = (mfContext*) instance->context;
mfc->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
mfc->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->instance->PreConnect = mac_pre_connect;
context->instance->PostConnect = mac_post_connect;
context->instance->ReceiveChannelData = mac_receive_channel_data;
context->instance->Authenticate = mac_authenticate;
context->instance->PreConnect = mac_pre_connect;
context->instance->PostConnect = mac_post_connect;
context->instance->ReceiveChannelData = mac_receive_channel_data;
context->instance->Authenticate = mac_authenticate;
context->channels = freerdp_channels_new();
context->channels = freerdp_channels_new();
settings = instance->settings;
settings->AsyncUpdate = TRUE;
settings->AsyncInput = TRUE;
settings->AsyncUpdate = TRUE;
settings->AsyncInput = TRUE;
settings->AsyncChannels = TRUE;
settings->AsyncTransport = TRUE;
settings->RedirectClipboard = TRUE;
settings->OsMajorType = OSMAJORTYPE_MACINTOSH;
settings->OsMinorType = OSMINORTYPE_MACINTOSH;
@ -193,6 +168,40 @@ void freerdp_client_mouse_event(rdpContext* cfc, DWORD flags, int x, int y)
input->MouseEvent(input, flags, x, y);
}
void mf_scale_mouse_event(void* context, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
{
mfContext* mfc = (mfContext*) context;
MRDPView* view = (MRDPView*) mfc->view;
int ww, wh, dw, dh;
ww = mfc->client_width;
wh = mfc->client_height;
dw = mfc->context.settings->DesktopWidth;
dh = mfc->context.settings->DesktopHeight;
// Convert to windows coordinates
y = [view frame].size.height - y;
if (!mfc->context.settings->SmartSizing || ((ww == dw) && (wh == dh)))
{
y = y + mfc->yCurrentScroll;
if (wh != dh)
{
y -= (dh - wh);
}
input->MouseEvent(input, flags, x + mfc->xCurrentScroll, y);
}
else
{
y = y * dh / wh + mfc->yCurrentScroll;
input->MouseEvent(input, flags, x * dw / ww + mfc->xCurrentScroll, y);
}
}
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
{
pEntryPoints->Version = 1;

View File

@ -321,7 +321,7 @@ int main(int argc, char* argv[])
channels = instance->context->channels;
status = freerdp_client_parse_command_line_arguments(argc, argv, instance->settings);
status = freerdp_client_settings_parse_command_line(instance->settings, argc, argv);
if (status < 0)
exit(0);

View File

@ -63,7 +63,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
if(WITH_CLIENT_INTERFACE)
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries EXPORT WinPRTargets)
add_subdirectory(cli)
else()
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)

View File

@ -70,9 +70,9 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
for (index = 0; index < context->argc; index++)
context->argv[index] = _strdup(__argv[index]);
status = freerdp_client_parse_command_line(context, context->argc, context->argv);
status = freerdp_client_settings_parse_command_line(settings, context->argc, context->argv);
status = freerdp_client_command_line_status_print(context->argc, context->argv, settings, status);
status = freerdp_client_settings_command_line_status_print(settings, status, context->argc, context->argv);
if (status)
{

View File

@ -588,7 +588,7 @@ void wf_scale_mouse_event(wfContext* wfc, rdpInput* input, UINT16 flags, UINT16
dw = wfc->instance->settings->DesktopWidth;
dh = wfc->instance->settings->DesktopHeight;
if (!wfc->instance->settings->SmartSizing || (ww == dw) && (wh == dh))
if (!wfc->instance->settings->SmartSizing || ((ww == dw) && (wh == dh)))
input->MouseEvent(input, flags, x + wfc->xCurrentScroll, y + wfc->yCurrentScroll);
else
input->MouseEvent(input, flags, x * dw / ww + wfc->xCurrentScroll, y * dh / wh + wfc->yCurrentScroll);

View File

@ -10,7 +10,7 @@
* 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
* 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,
@ -49,6 +49,7 @@
#include <freerdp/client/cmdline.h>
#include <freerdp/client/channels.h>
#include <freerdp/channels/channels.h>
#include <freerdp/event.h>
#include "wf_gdi.h"
#include "wf_graphics.h"
@ -331,6 +332,7 @@ BOOL wf_post_connect(freerdp* instance)
rdpContext* context;
WCHAR lpWindowName[64];
rdpSettings* settings;
EmbedWindowEventArgs e;
settings = instance->settings;
context = instance->context;
@ -388,6 +390,9 @@ BOOL wf_post_connect(freerdp* instance)
else
_snwprintf(lpWindowName, ARRAYSIZE(lpWindowName), L"FreeRDP: %S:%d", settings->ServerHostname, settings->ServerPort);
if (settings->EmbeddedWindow)
settings->Decorations = FALSE;
if (!settings->Decorations)
dwStyle = WS_CHILD | WS_BORDER;
else
@ -398,7 +403,7 @@ BOOL wf_post_connect(freerdp* instance)
wfc->hwnd = CreateWindowEx((DWORD) NULL, wfc->wndClassName, lpWindowName, dwStyle,
0, 0, 0, 0, wfc->hWndParent, NULL, wfc->hInstance, NULL);
SetWindowLongPtr(wfc->hwnd, GWLP_USERDATA, (LONG_PTR) wfc);
SetWindowLongPtr(wfc->hwnd, GWLP_USERDATA, (LONG_PTR) wfc);
}
wf_resize_window(wfc);
@ -408,6 +413,11 @@ BOOL wf_post_connect(freerdp* instance)
BitBlt(wfc->primary->hdc, 0, 0, wfc->width, wfc->height, NULL, 0, 0, BLACKNESS);
wfc->drawing = wfc->primary;
EventArgsInit(&e, "wfreerdp");
e.embed = FALSE;
e.handle = (void*) wfc->hwnd;
PubSub_OnEmbedWindow(context->pubSub, context, &e);
ShowWindow(wfc->hwnd, SW_SHOWNORMAL);
UpdateWindow(wfc->hwnd);
@ -778,6 +788,8 @@ int freerdp_client_focus_out(wfContext* wfc)
int freerdp_client_set_window_size(wfContext* wfc, int width, int height)
{
fprintf(stderr, "freerdp_client_set_window_size %d, %d", width, height);
if ((width != wfc->client_width) || (height != wfc->client_height))
{
PostThreadMessage(wfc->mainThreadId, WM_SIZE, SIZE_RESTORED, ((UINT) height << 16) | (UINT) width);
@ -786,19 +798,19 @@ int freerdp_client_set_window_size(wfContext* wfc, int width, int height)
return 0;
}
void wf_on_param_change(freerdp* instance, int id)
void wf_ParamChangeEventHandler(rdpContext* context, ParamChangeEventArgs* e)
{
RECT rect;
HMENU hMenu;
wfContext* wfc = (wfContext*) instance->context;
wfContext* wfc = (wfContext*) context;
// specific processing here
switch (id)
switch (e->id)
{
case FreeRDP_SmartSizing:
fprintf(stderr, "SmartSizing changed.\n");
if (!instance->settings->SmartSizing && (wfc->client_width > instance->settings->DesktopWidth || wfc->client_height > instance->settings->DesktopHeight))
if (!context->settings->SmartSizing && (wfc->client_width > context->settings->DesktopWidth || wfc->client_height > context->settings->DesktopHeight))
{
GetWindowRect(wfc->hwnd, &rect);
SetWindowPos(wfc->hwnd, HWND_TOP, 0, 0, MIN(wfc->client_width + wfc->offset_x, rect.right - rect.left), MIN(wfc->client_height + wfc->offset_y, rect.bottom - rect.top), SWP_NOMOVE | SWP_FRAMECHANGED);
@ -806,7 +818,7 @@ void wf_on_param_change(freerdp* instance, int id)
}
hMenu = GetSystemMenu(wfc->hwnd, FALSE);
CheckMenuItem(hMenu, SYSCOMMAND_ID_SMARTSIZING, instance->settings->SmartSizing);
CheckMenuItem(hMenu, SYSCOMMAND_ID_SMARTSIZING, context->settings->SmartSizing);
wf_size_scrollbars(wfc, wfc->client_width, wfc->client_height);
GetClientRect(wfc->hwnd, &rect);
InvalidateRect(wfc->hwnd, &rect, TRUE);
@ -1036,6 +1048,8 @@ int wfreerdp_client_new(freerdp* instance, rdpContext* context)
wfc->instance = instance;
context->channels = freerdp_channels_new();
PubSub_SubscribeParamChange(context->pubSub, wf_ParamChangeEventHandler);
return 0;
}

View File

@ -140,6 +140,8 @@ typedef struct wf_context wfContext;
*/
FREERDP_API int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints);
FREERDP_API int freerdp_client_set_window_size(wfContext* wfc, int width, int height);
#ifdef __cplusplus
}

View File

@ -204,7 +204,7 @@ if(WITH_IPP)
endif()
if(WITH_CLIENT_INTERFACE)
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries EXPORT FreeRDPTargets)
add_subdirectory(cli)
else()
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)

View File

@ -53,9 +53,9 @@ int main(int argc, char* argv[])
settings = context->settings;
xfc = (xfContext*) context;
status = freerdp_client_parse_command_line(context, argc, argv);
status = freerdp_client_settings_parse_command_line(context->settings, argc, argv);
status = freerdp_client_command_line_status_print(argc, argv, settings, status);
status = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
if (status)
{

View File

@ -728,8 +728,12 @@ static void xf_post_disconnect(freerdp *instance)
assert(NULL != xfc);
assert(NULL != instance->settings);
WaitForSingleObject(xfc->mutex, INFINITE);
CloseHandle(xfc->mutex);
if (xfc->mutex)
{
WaitForSingleObject(xfc->mutex, INFINITE);
CloseHandle(xfc->mutex);
xfc->mutex = NULL;
}
xf_monitors_free(xfc, instance->settings);
}
@ -750,13 +754,41 @@ BOOL xf_pre_connect(freerdp* instance)
rdpSettings* settings;
xfContext* xfc = (xfContext*) instance->context;
xfc->mutex = CreateMutex(NULL, FALSE, NULL);
xfc->settings = instance->settings;
xfc->instance = instance;
settings = instance->settings;
channels = instance->context->channels;
xfc->UseXThreads = TRUE;
if (xfc->UseXThreads)
{
if (!XInitThreads())
{
fprintf(stderr, "warning: XInitThreads() failure\n");
xfc->UseXThreads = FALSE;
}
}
xfc->display = XOpenDisplay(NULL);
if (!xfc->display)
{
fprintf(stderr, "xf_pre_connect: failed to open display: %s\n", XDisplayName(NULL));
fprintf(stderr, "Please check that the $DISPLAY environment variable is properly set.\n");
return FALSE;
}
if (xfc->debug)
{
fprintf(stderr, "Enabling X11 debug mode.\n");
XSynchronize(xfc->display, TRUE);
_def_error_handler = XSetErrorHandler(_xf_error_handler);
}
xfc->mutex = CreateMutex(NULL, FALSE, NULL);
PubSub_SubscribeChannelConnected(instance->context->pubSub,
(pChannelConnectedEventHandler) xf_OnChannelConnectedEventHandler);
@ -785,33 +817,6 @@ BOOL xf_pre_connect(freerdp* instance)
return TRUE;
}
xfc->UseXThreads = TRUE;
if (xfc->UseXThreads)
{
if (!XInitThreads())
{
fprintf(stderr, "warning: XInitThreads() failure\n");
xfc->UseXThreads = FALSE;
}
}
xfc->display = XOpenDisplay(NULL);
if (!xfc->display)
{
fprintf(stderr, "xf_pre_connect: failed to open display: %s\n", XDisplayName(NULL));
fprintf(stderr, "Please check that the $DISPLAY environment variable is properly set.\n");
return FALSE;
}
if (xfc->debug)
{
fprintf(stderr, "Enabling X11 debug mode.\n");
XSynchronize(xfc->display, TRUE);
_def_error_handler = XSetErrorHandler(_xf_error_handler);
}
xfc->_NET_WM_ICON = XInternAtom(xfc->display, "_NET_WM_ICON", False);
xfc->_MOTIF_WM_HINTS = XInternAtom(xfc->display, "_MOTIF_WM_HINTS", False);
xfc->_NET_CURRENT_DESKTOP = XInternAtom(xfc->display, "_NET_CURRENT_DESKTOP", False);
@ -937,6 +942,10 @@ BOOL xf_post_connect(freerdp* instance)
xf_create_window(xfc);
ZeroMemory(&gcv, sizeof(gcv));
if (xfc->modifier_map)
XFreeModifiermap(xfc->modifier_map);
xfc->modifier_map = XGetModifierMapping(xfc->display);
xfc->gc = XCreateGC(xfc->display, xfc->drawable, GCGraphicsExposures, &gcv);
@ -1388,6 +1397,15 @@ void* xf_thread(void* param)
if (!status)
{
if (xfc->mutex)
{
WaitForSingleObject(xfc->mutex, INFINITE);
CloseHandle(xfc->mutex);
xfc->mutex = NULL;
}
xf_monitors_free(xfc, instance->settings);
exit_code = XF_EXIT_CONN_FAILED;
ExitThread(exit_code);
}
@ -1754,6 +1772,7 @@ static int xfreerdp_client_stop(rdpContext* context)
xfContext* xfc = (xfContext*) context;
assert(NULL != context);
if (context->settings->AsyncInput)
{
wMessageQueue* queue;
@ -1828,7 +1847,6 @@ static int xfreerdp_client_new(freerdp* instance, rdpContext* context)
PubSub_SubscribeParamChange(context->pubSub, (pParamChangeEventHandler) xf_ParamChangeEventHandler);
PubSub_SubscribeScalingFactorChange(context->pubSub, (pScalingFactorChangeEventHandler) xf_ScalingFactorChangeEventHandler);
return 0;
}

View File

@ -475,7 +475,9 @@ static BOOL xf_event_MappingNotify(xfContext* xfc, XEvent* event, BOOL app)
{
if (event->xmapping.request == MappingModifier)
{
XFreeModifiermap(xfc->modifier_map);
if (xfc->modifier_map)
XFreeModifiermap(xfc->modifier_map);
xfc->modifier_map = XGetModifierMapping(xfc->display);
}

View File

@ -38,9 +38,14 @@
void xf_kbd_init(xfContext* xfc)
{
xf_kbd_clear(xfc);
xfc->keyboard_layout_id = xfc->instance->settings->KeyboardLayout;
xfc->keyboard_layout_id = freerdp_keyboard_init(xfc->keyboard_layout_id);
xfc->instance->settings->KeyboardLayout = xfc->keyboard_layout_id;
if (xfc->modifier_map)
XFreeModifiermap(xfc->modifier_map);
xfc->modifier_map = XGetModifierMapping(xfc->display);
}

View File

@ -261,10 +261,16 @@ BOOL xf_detect_monitors(xfContext* xfc, rdpSettings* settings)
void xf_monitors_free(xfContext *xfc, rdpSettings *settings)
{
#ifdef WITH_XINERAMA
if(xfc->vscreen.monitors)
if (xfc->vscreen.monitors)
{
free(xfc->vscreen.monitors);
xfc->vscreen.monitors = NULL;
}
#endif
if(settings->MonitorIds)
if (settings->MonitorIds)
{
free(settings->MonitorIds);
settings->MonitorIds = NULL;
}
}

View File

@ -662,9 +662,9 @@ void xf_process_rail_appid_resp_event(xfContext* xfc, rdpChannels* channels, wMe
fprintf(stderr, "Server Application ID Response PDU: windowId=0x%X "
"applicationId=(length=%d dump)\n",
appid_resp->windowId, appid_resp->applicationId.length);
appid_resp->windowId, 512);
winpr_HexDump(appid_resp->applicationId.string, appid_resp->applicationId.length);
winpr_HexDump((BYTE*) &appid_resp->applicationId, 512);
}
void xf_process_rail_langbarinfo_event(xfContext* xfc, rdpChannels* channels, wMessage* event)

View File

@ -18,6 +18,9 @@
set(MODULE_NAME "freerdp-client")
set(MODULE_PREFIX "FREERDP_CLIENT")
include_directories(${OPENSSL_INCLUDE_DIR})
include_directories(${ZLIB_INCLUDE_DIRS})
set(${MODULE_PREFIX}_SRCS
client.c
cmdline.c
@ -50,9 +53,11 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHI
MODULE winpr
MODULES winpr-crt winpr-utils)
set_target_properties(${MODULE_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "")
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Common")

View File

@ -50,6 +50,7 @@ rdpContext* freerdp_client_context_new(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
pEntryPoints->GlobalInit();
instance = freerdp_new();
instance->settings = pEntryPoints->settings;
instance->ContextSize = pEntryPoints->ContextSize;
instance->ContextNew = freerdp_client_common_new;
instance->ContextFree = freerdp_client_common_free;
@ -70,9 +71,12 @@ void freerdp_client_context_free(rdpContext* context)
{
freerdp* instance = context->instance;
free(instance->pClientEntryPoints);
freerdp_context_free(instance);
freerdp_free(instance);
if (instance)
{
freerdp_context_free(instance);
free(instance->pClientEntryPoints);
freerdp_free(instance);
}
}
int freerdp_client_start(rdpContext* context)
@ -97,45 +101,39 @@ HANDLE freerdp_client_get_thread(rdpContext* context)
return ((rdpClientContext*) context)->thread;
}
int freerdp_client_parse_command_line(rdpContext* context, int argc, char** argv)
int freerdp_client_settings_parse_command_line(rdpSettings* settings, int argc, char** argv)
{
int status;
rdpSettings* settings;
context->argc = argc;
context->argv = argv;
if (context->argc < 1)
if (argc < 1)
return 0;
if (!context->argv)
if (!argv)
return -1;
settings = context->settings;
status = freerdp_client_parse_command_line_arguments(context->argc, context->argv, settings);
status = freerdp_client_settings_parse_command_line_arguments(settings, argc, argv);
if (settings->ConnectionFile)
{
status = freerdp_client_parse_connection_file(context, settings->ConnectionFile);
status = freerdp_client_settings_parse_connection_file(settings, settings->ConnectionFile);
}
return status;
}
int freerdp_client_parse_connection_file(rdpContext* context, const char* filename)
int freerdp_client_settings_parse_connection_file(rdpSettings* settings, const char* filename)
{
rdpFile* file;
file = freerdp_client_rdp_file_new();
freerdp_client_parse_rdp_file(file, filename);
freerdp_client_populate_settings_from_rdp_file(file, context->settings);
freerdp_client_populate_settings_from_rdp_file(file, settings);
freerdp_client_rdp_file_free(file);
return 0;
}
int freerdp_client_parse_connection_file_buffer(rdpContext* context, BYTE* buffer, size_t size)
int freerdp_client_settings_parse_connection_file_buffer(rdpSettings* settings, BYTE* buffer, size_t size)
{
rdpFile* file;
int status = -1;
@ -143,7 +141,7 @@ int freerdp_client_parse_connection_file_buffer(rdpContext* context, BYTE* buffe
file = freerdp_client_rdp_file_new();
if (freerdp_client_parse_rdp_file_buffer(file, buffer, size)
&& freerdp_client_populate_settings_from_rdp_file(file, context->settings))
&& freerdp_client_populate_settings_from_rdp_file(file, settings))
{
status = 0;
}
@ -153,14 +151,14 @@ int freerdp_client_parse_connection_file_buffer(rdpContext* context, BYTE* buffe
return status;
}
int freerdp_client_write_connection_file(rdpContext* context, const char* filename, BOOL unicode)
int freerdp_client_settings_write_connection_file(rdpSettings* settings, const char* filename, BOOL unicode)
{
rdpFile* file;
int status = -1;
file = freerdp_client_rdp_file_new();
if (freerdp_client_populate_rdp_file_from_settings(file, context->settings))
if (freerdp_client_populate_rdp_file_from_settings(file, settings))
{
if (freerdp_client_write_rdp_file(file, filename, unicode))
{

View File

@ -52,6 +52,8 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "kbd-subtype", COMMAND_LINE_VALUE_REQUIRED, "<subtype id>", NULL, NULL, -1, NULL, "Keyboard subtype" },
{ "kbd-fn-key", COMMAND_LINE_VALUE_REQUIRED, "<function key count>", NULL, NULL, -1, NULL, "Keyboard function key count" },
{ "admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "console", "Admin (or console) session" },
{ "restricted-admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "restrictedAdmin", "Restricted admin mode" },
{ "pth", COMMAND_LINE_VALUE_REQUIRED, "<password hash>", NULL, NULL, -1, "pass-the-hash", "Pass the hash (restricted admin mode)" },
{ "multimon", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Use multiple monitors" },
{ "workarea", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Use available work area" },
{ "monitors", COMMAND_LINE_VALUE_REQUIRED, "<0,1,2...>", NULL, NULL, -1, NULL, "Select monitors to use" },
@ -104,6 +106,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "themes", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Themes" },
{ "wallpaper", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Wallpaper" },
{ "gdi", COMMAND_LINE_VALUE_REQUIRED, "<sw|hw>", NULL, NULL, -1, NULL, "GDI rendering" },
{ "gfx", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" },
{ "rfx", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "RemoteFX" },
{ "rfx-mode", COMMAND_LINE_VALUE_REQUIRED, "<image|video>", NULL, NULL, -1, NULL, "RemoteFX mode" },
{ "frame-ack", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Frame acknowledgement" },
@ -1010,7 +1013,7 @@ BOOL freerdp_client_detect_command_line(int argc, char** argv, DWORD* flags)
return compatibility;
}
int freerdp_client_command_line_status_print(int argc, char** argv, rdpSettings* settings, int status)
int freerdp_client_settings_command_line_status_print(rdpSettings* settings, int status, int argc, char** argv)
{
COMMAND_LINE_ARGUMENT_A* arg;
@ -1067,7 +1070,7 @@ int freerdp_client_command_line_status_print(int argc, char** argv, rdpSettings*
return 0;
}
int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettings* settings)
int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, int argc, char** argv)
{
char* p;
char* str;
@ -1231,6 +1234,17 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
{
settings->ConsoleSession = TRUE;
}
CommandLineSwitchCase(arg, "restricted-admin")
{
settings->ConsoleSession = TRUE;
settings->RestrictedAdminModeRequired = TRUE;
}
CommandLineSwitchCase(arg, "pth")
{
settings->ConsoleSession = TRUE;
settings->RestrictedAdminModeRequired = TRUE;
settings->PasswordHash = _strdup(arg->Value);
}
CommandLineSwitchCase(arg, "kbd")
{
int id;
@ -1470,6 +1484,10 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
else if (strcmp(arg->Value, "hw") == 0)
settings->SoftwareGdi = FALSE;
}
CommandLineSwitchCase(arg, "gfx")
{
settings->SupportGraphicsPipeline = TRUE;
}
CommandLineSwitchCase(arg, "rfx")
{
settings->RemoteFxCodec = TRUE;
@ -1492,7 +1510,10 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
CommandLineSwitchCase(arg, "nsc")
{
settings->NSCodec = TRUE;
settings->FastPathOutput = TRUE;
settings->ColorDepth = 32;
settings->LargePointerFlag = TRUE;
settings->FrameMarkerCommandEnabled = TRUE;
}
CommandLineSwitchCase(arg, "jpeg")
{
@ -1740,7 +1761,7 @@ int freerdp_client_load_static_channel_addin(rdpChannels* channels, rdpSettings*
{
void* entry;
entry = freerdp_load_channel_addin_entry(name, NULL, NULL, 0);
entry = freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC);
if (entry)
{
@ -1841,6 +1862,17 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings)
freerdp_client_load_static_channel_addin(channels, settings, "rail", settings);
}
if (settings->SupportGraphicsPipeline)
{
char* p[1];
int count;
count = 1;
p[0] = "rdpgfx";
freerdp_client_add_dynamic_channel(settings, count, p);
}
if (settings->DynamicChannelCount)
{
freerdp_client_load_static_channel_addin(channels, settings, "drdynvc", settings);

View File

@ -321,10 +321,15 @@ int freerdp_detect_old_command_line_syntax(int argc, char** argv, int* count)
ZeroMemory(settings, sizeof(rdpSettings));
CommandLineClearArgumentsA(old_args);
status = CommandLineParseArgumentsA(argc, (const char**) argv, old_args, flags, settings,
freerdp_client_old_command_line_pre_filter, NULL);
if (status < 0)
{
free(settings);
return status;
}
arg = old_args;

View File

@ -481,6 +481,7 @@ BOOL freerdp_client_parse_rdp_file_buffer(rdpFile* file, BYTE* buffer, size_t si
BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name)
{
BOOL status;
BYTE* buffer;
FILE* fp = NULL;
size_t read_size;
@ -521,11 +522,15 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name)
buffer[file_size] = '\0';
buffer[file_size + 1] = '\0';
return freerdp_client_parse_rdp_file_buffer(file, buffer, file_size);
status = freerdp_client_parse_rdp_file_buffer(file, buffer, file_size);
free(buffer);
return status;
}
#define WRITE_ALL_SETTINGS FALSE
#define SETTING_MODIFIED(_settings, _field) (WRITE_ALL_SETTINGS || _settings->settings_modified[FreeRDP_##_field])
#define WRITE_ALL_SETTINGS TRUE
#define SETTING_MODIFIED(_settings, _field) (WRITE_ALL_SETTINGS || _settings->SettingsModified[FreeRDP_##_field])
#define SETTING_MODIFIED_SET(_target, _settings, _field) if SETTING_MODIFIED(_settings, _field) _target = _settings->_field
BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings* settings)
@ -960,12 +965,18 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
if (file->argc > 1)
{
freerdp_client_parse_command_line_arguments(file->argc, file->argv, settings);
freerdp_client_settings_parse_command_line(settings, file->argc, file->argv);
}
return TRUE;
}
void freerdp_client_file_string_check_free(LPSTR str)
{
if (~((size_t) str))
free(str);
}
rdpFile* freerdp_client_rdp_file_new()
{
rdpFile* file;
@ -1000,6 +1011,26 @@ void freerdp_client_rdp_file_free(rdpFile* file)
free(file->argv);
}
freerdp_client_file_string_check_free(file->Username);
freerdp_client_file_string_check_free(file->Domain);
freerdp_client_file_string_check_free(file->FullAddress);
freerdp_client_file_string_check_free(file->AlternateFullAddress);
freerdp_client_file_string_check_free(file->UsbDevicesToRedirect);
freerdp_client_file_string_check_free(file->LoadBalanceInfo);
freerdp_client_file_string_check_free(file->RemoteApplicationName);
freerdp_client_file_string_check_free(file->RemoteApplicationIcon);
freerdp_client_file_string_check_free(file->RemoteApplicationProgram);
freerdp_client_file_string_check_free(file->RemoteApplicationFile);
freerdp_client_file_string_check_free(file->RemoteApplicationGuid);
freerdp_client_file_string_check_free(file->RemoteApplicationCmdLine);
freerdp_client_file_string_check_free(file->AlternateShell);
freerdp_client_file_string_check_free(file->ShellWorkingDirectory);
freerdp_client_file_string_check_free(file->GatewayHostname);
freerdp_client_file_string_check_free(file->KdcProxyName);
freerdp_client_file_string_check_free(file->DrivesToRedirect);
freerdp_client_file_string_check_free(file->DevicesToRedirect);
freerdp_client_file_string_check_free(file->WinPosStr);
free(file);
}
}

View File

@ -22,7 +22,8 @@ macro(enable_cmake_compat CMVERSION)
endif()
endmacro()
# Compatibility includes - oder does matter!
# Compatibility includes - order does matter!
enable_cmake_compat(2.8.11)
enable_cmake_compat(2.8.6)
enable_cmake_compat(2.8.3)
enable_cmake_compat(2.8.2)

View File

@ -0,0 +1,31 @@
# This is a basic version file for the Config-mode of find_package().
# It is used by write_basic_package_version_file() as input file for configure_file()
# to create a version-file which can be installed along a config.cmake file.
#
# The created file sets PACKAGE_VERSION_EXACT if the current version string and
# the requested version string are exactly the same and it sets
# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version.
# The variable CVF_VERSION must be set before calling configure_file().
set(PACKAGE_VERSION "@CVF_VERSION@")
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" )
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "")
return()
endif()
# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "@CMAKE_SIZEOF_VOID_P@")
math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8")
set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
set(PACKAGE_VERSION_UNSUITABLE TRUE)
endif()

View File

@ -0,0 +1,47 @@
# This is a basic version file for the Config-mode of find_package().
# It is used by write_basic_package_version_file() as input file for configure_file()
# to create a version-file which can be installed along a config.cmake file.
#
# The created file sets PACKAGE_VERSION_EXACT if the current version string and
# the requested version string are exactly the same and it sets
# PACKAGE_VERSION_COMPATIBLE if the current version is equal to the requested version.
# The tweak version component is ignored.
# The variable CVF_VERSION must be set before calling configure_file().
set(PACKAGE_VERSION "@CVF_VERSION@")
if("@CVF_VERSION@" MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)\\..*") # strip the tweak version
set(CVF_VERSION_NO_TWEAK "${CMAKE_MATCH_1}")
else()
set(CVF_VERSION_NO_TWEAK "@CVF_VERSION@")
endif()
if("${PACKAGE_FIND_VERSION}" MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)\\..*") # strip the tweak version
set(REQUESTED_VERSION_NO_TWEAK "${CMAKE_MATCH_1}")
else()
set(REQUESTED_VERSION_NO_TWEAK "${PACKAGE_FIND_VERSION}")
endif()
if("${REQUESTED_VERSION_NO_TWEAK}" STREQUAL "${CVF_VERSION_NO_TWEAK}")
set(PACKAGE_VERSION_COMPATIBLE TRUE)
else()
set(PACKAGE_VERSION_COMPATIBLE FALSE)
endif()
if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "")
return()
endif()
# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "@CMAKE_SIZEOF_VOID_P@")
math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8")
set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
set(PACKAGE_VERSION_UNSUITABLE TRUE)
endif()

View File

@ -0,0 +1,46 @@
# This is a basic version file for the Config-mode of find_package().
# It is used by write_basic_package_version_file() as input file for configure_file()
# to create a version-file which can be installed along a config.cmake file.
#
# The created file sets PACKAGE_VERSION_EXACT if the current version string and
# the requested version string are exactly the same and it sets
# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version,
# but only if the requested major version is the same as the current one.
# The variable CVF_VERSION must be set before calling configure_file().
set(PACKAGE_VERSION "@CVF_VERSION@")
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" )
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
if("@CVF_VERSION@" MATCHES "^([0-9]+)\\.")
set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
else()
set(CVF_VERSION_MAJOR "@CVF_VERSION@")
endif()
if("${PACKAGE_FIND_VERSION_MAJOR}" STREQUAL "${CVF_VERSION_MAJOR}")
set(PACKAGE_VERSION_COMPATIBLE TRUE)
else()
set(PACKAGE_VERSION_COMPATIBLE FALSE)
endif()
if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "@CMAKE_SIZEOF_VOID_P@" STREQUAL "")
return()
endif()
# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "@CMAKE_SIZEOF_VOID_P@")
math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8")
set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
set(PACKAGE_VERSION_UNSUITABLE TRUE)
endif()

View File

@ -0,0 +1,248 @@
# - CONFIGURE_PACKAGE_CONFIG_FILE(), WRITE_BASIC_PACKAGE_VERSION_FILE()
#
# CONFIGURE_PACKAGE_CONFIG_FILE(<input> <output> INSTALL_DESTINATION <path>
# [PATH_VARS <var1> <var2> ... <varN>]
# [NO_SET_AND_CHECK_MACRO]
# [NO_CHECK_REQUIRED_COMPONENTS_MACRO])
#
# CONFIGURE_PACKAGE_CONFIG_FILE() should be used instead of the plain
# configure_file() command when creating the <Name>Config.cmake or <Name>-config.cmake
# file for installing a project or library. It helps making the resulting package
# relocatable by avoiding hardcoded paths in the installed Config.cmake file.
#
# In a FooConfig.cmake file there may be code like this to make the
# install destinations know to the using project:
# set(FOO_INCLUDE_DIR "@CMAKE_INSTALL_FULL_INCLUDEDIR@" )
# set(FOO_DATA_DIR "@CMAKE_INSTALL_PREFIX@/@RELATIVE_DATA_INSTALL_DIR@" )
# set(FOO_ICONS_DIR "@CMAKE_INSTALL_PREFIX@/share/icons" )
# ...logic to determine installedPrefix from the own location...
# set(FOO_CONFIG_DIR "${installedPrefix}/@CONFIG_INSTALL_DIR@" )
# All 4 options shown above are not sufficient, since the first 3 hardcode
# the absolute directory locations, and the 4th case works only if the logic
# to determine the installedPrefix is correct, and if CONFIG_INSTALL_DIR contains
# a relative path, which in general cannot be guaranteed.
# This has the effect that the resulting FooConfig.cmake file would work poorly
# under Windows and OSX, where users are used to choose the install location
# of a binary package at install time, independent from how CMAKE_INSTALL_PREFIX
# was set at build/cmake time.
#
# Using CONFIGURE_PACKAGE_CONFIG_FILE() helps. If used correctly, it makes the
# resulting FooConfig.cmake file relocatable.
# Usage:
# 1. write a FooConfig.cmake.in file as you are used to
# 2. insert a line containing only the string "@PACKAGE_INIT@"
# 3. instead of set(FOO_DIR "@SOME_INSTALL_DIR@"), use set(FOO_DIR "@PACKAGE_SOME_INSTALL_DIR@")
# (this must be after the @PACKAGE_INIT@ line)
# 4. instead of using the normal configure_file(), use CONFIGURE_PACKAGE_CONFIG_FILE()
#
# The <input> and <output> arguments are the input and output file, the same way
# as in configure_file().
#
# The <path> given to INSTALL_DESTINATION must be the destination where the FooConfig.cmake
# file will be installed to. This can either be a relative or absolute path, both work.
#
# The variables <var1> to <varN> given as PATH_VARS are the variables which contain
# install destinations. For each of them the macro will create a helper variable
# PACKAGE_<var...>. These helper variables must be used
# in the FooConfig.cmake.in file for setting the installed location. They are calculated
# by CONFIGURE_PACKAGE_CONFIG_FILE() so that they are always relative to the
# installed location of the package. This works both for relative and also for absolute locations.
# For absolute locations it works only if the absolute location is a subdirectory
# of CMAKE_INSTALL_PREFIX.
#
# By default configure_package_config_file() also generates two helper macros,
# set_and_check() and check_required_components() into the FooConfig.cmake file.
#
# set_and_check() should be used instead of the normal set()
# command for setting directories and file locations. Additionally to setting the
# variable it also checks that the referenced file or directory actually exists
# and fails with a FATAL_ERROR otherwise. This makes sure that the created
# FooConfig.cmake file does not contain wrong references.
# When using the NO_SET_AND_CHECK_MACRO, this macro is not generated into the
# FooConfig.cmake file.
#
# check_required_components(<package_name>) should be called at the end of the
# FooConfig.cmake file if the package supports components.
# This macro checks whether all requested, non-optional components have been found,
# and if this is not the case, sets the Foo_FOUND variable to FALSE, so that the package
# is considered to be not found.
# It does that by testing the Foo_<Component>_FOUND variables for all requested
# required components.
# When using the NO_CHECK_REQUIRED_COMPONENTS option, this macro is not generated
# into the FooConfig.cmake file.
#
# For an example see below the documentation for WRITE_BASIC_PACKAGE_VERSION_FILE().
#
#
# WRITE_BASIC_PACKAGE_VERSION_FILE( filename VERSION major.minor.patch COMPATIBILITY (AnyNewerVersion|SameMajorVersion|ExactVersion) )
#
# Writes a file for use as <package>ConfigVersion.cmake file to <filename>.
# See the documentation of find_package() for details on this.
# filename is the output filename, it should be in the build tree.
# major.minor.patch is the version number of the project to be installed
# The COMPATIBILITY mode AnyNewerVersion means that the installed package version
# will be considered compatible if it is newer or exactly the same as the requested version.
# This mode should be used for packages which are fully backward compatible,
# also across major versions.
# If SameMajorVersion is used instead, then the behaviour differs from AnyNewerVersion
# in that the major version number must be the same as requested, e.g. version 2.0 will
# not be considered compatible if 1.0 is requested.
# This mode should be used for packages which guarantee backward compatibility within the
# same major version.
# If ExactVersion is used, then the package is only considered compatible if the requested
# version matches exactly its own version number (not considering the tweak version).
# For example, version 1.2.3 of a package is only considered compatible to requested version 1.2.3.
# This mode is for packages without compatibility guarantees.
# If your project has more elaborated version matching rules, you will need to write your
# own custom ConfigVersion.cmake file instead of using this macro.
#
# Internally, this macro executes configure_file() to create the resulting
# version file. Depending on the COMPATIBLITY, either the file
# BasicConfigVersion-SameMajorVersion.cmake.in or BasicConfigVersion-AnyNewerVersion.cmake.in
# is used. Please note that these two files are internal to CMake and you should
# not call configure_file() on them yourself, but they can be used as starting
# point to create more sophisticted custom ConfigVersion.cmake files.
#
#
# Example using both configure_package_config_file() and write_basic_package_version_file():
# CMakeLists.txt:
# set(INCLUDE_INSTALL_DIR include/ ... CACHE )
# set(LIB_INSTALL_DIR lib/ ... CACHE )
# set(SYSCONFIG_INSTALL_DIR etc/foo/ ... CACHE )
# ...
# include(CMakePackageConfigHelpers)
# configure_package_config_file(FooConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake
# INSTALL_DESTINATION ${LIB_INSTALL_DIR}/Foo/cmake
# PATH_VARS INCLUDE_INSTALL_DIR SYSCONFIG_INSTALL_DIR)
# write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake
# VERSION 1.2.3
# COMPATIBILITY SameMajorVersion )
# install(FILES ${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake
# DESTINATION ${LIB_INSTALL_DIR}/Foo/cmake )
#
# With a FooConfig.cmake.in:
# set(FOO_VERSION x.y.z)
# ...
# @PACKAGE_INIT@
# ...
# set_and_check(FOO_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
# set_and_check(FOO_SYSCONFIG_DIR "@PACKAGE_SYSCONFIG_INSTALL_DIR@")
#
# check_required_components(Foo)
#=============================================================================
# Copyright 2012 Alexander Neundorf <neundorf@kde.org>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
include(CMakeParseArguments)
include(WriteBasicConfigVersionFile)
macro(WRITE_BASIC_PACKAGE_VERSION_FILE)
write_basic_config_version_file(${ARGN})
endmacro()
function(CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile)
set(options NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO)
set(oneValueArgs INSTALL_DESTINATION )
set(multiValueArgs PATH_VARS )
cmake_parse_arguments(CCF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(CCF_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown keywords given to CONFIGURE_PACKAGE_CONFIG_FILE(): \"${CCF_UNPARSED_ARGUMENTS}\"")
endif()
if(NOT CCF_INSTALL_DESTINATION)
message(FATAL_ERROR "No INSTALL_DESTINATION given to CONFIGURE_PACKAGE_CONFIG_FILE()")
endif()
if(IS_ABSOLUTE "${CCF_INSTALL_DESTINATION}")
set(absInstallDir "${CCF_INSTALL_DESTINATION}")
else()
set(absInstallDir "${CMAKE_INSTALL_PREFIX}/${CCF_INSTALL_DESTINATION}")
endif()
file(RELATIVE_PATH PACKAGE_RELATIVE_PATH "${absInstallDir}" "${CMAKE_INSTALL_PREFIX}" )
foreach(var ${CCF_PATH_VARS})
if(NOT DEFINED ${var})
message(FATAL_ERROR "Variable ${var} does not exist")
else()
if(IS_ABSOLUTE "${${var}}")
string(REPLACE "${CMAKE_INSTALL_PREFIX}" "\${PACKAGE_PREFIX_DIR}"
PACKAGE_${var} "${${var}}")
else()
set(PACKAGE_${var} "\${PACKAGE_PREFIX_DIR}/${${var}}")
endif()
endif()
endforeach()
get_filename_component(inputFileName "${_inputFile}" NAME)
set(PACKAGE_INIT "
####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() #######
####### Any changes to this file will be overwritten by the next CMake run ####
####### The input file was ${inputFileName} ########
get_filename_component(PACKAGE_PREFIX_DIR \"\${CMAKE_CURRENT_LIST_DIR}/${PACKAGE_RELATIVE_PATH}\" ABSOLUTE)
")
if("${absInstallDir}" MATCHES "^(/usr)?/lib(64)?/.+")
# Handle "/usr move" symlinks created by some Linux distros.
set(PACKAGE_INIT "${PACKAGE_INIT}
# Use original install prefix when loaded through a \"/usr move\"
# cross-prefix symbolic link such as /lib -> /usr/lib.
get_filename_component(_realCurr \"\${CMAKE_CURRENT_LIST_DIR}\" REALPATH)
get_filename_component(_realOrig \"${absInstallDir}\" REALPATH)
if(_realCurr STREQUAL _realOrig)
set(PACKAGE_PREFIX_DIR \"${CMAKE_INSTALL_PREFIX}\")
endif()
unset(_realOrig)
unset(_realCurr)
")
endif()
if(NOT CCF_NO_SET_AND_CHECK_MACRO)
set(PACKAGE_INIT "${PACKAGE_INIT}
macro(set_and_check _var _file)
set(\${_var} \"\${_file}\")
if(NOT EXISTS \"\${_file}\")
message(FATAL_ERROR \"File or directory \${_file} referenced by variable \${_var} does not exist !\")
endif()
endmacro()
")
endif()
if(NOT CCF_NO_CHECK_REQUIRED_COMPONENTS_MACRO)
set(PACKAGE_INIT "${PACKAGE_INIT}
macro(check_required_components _NAME)
foreach(comp \${\${_NAME}_FIND_COMPONENTS})
if(NOT \${_NAME}_\${comp}_FOUND)
if(\${_NAME}_FIND_REQUIRED_\${comp})
set(\${_NAME}_FOUND FALSE)
endif()
endif()
endforeach()
endmacro()
")
endif()
set(PACKAGE_INIT "${PACKAGE_INIT}
####################################################################################")
configure_file("${_inputFile}" "${_outputFile}" @ONLY)
endfunction()

View File

@ -0,0 +1,50 @@
# WRITE_BASIC_CONFIG_VERSION_FILE( filename VERSION major.minor.patch COMPATIBILITY (AnyNewerVersion|SameMajorVersion) )
#
# Deprecated, see WRITE_BASIC_PACKAGE_VERSION_FILE(), it is identical.
#=============================================================================
# Copyright 2008-2011 Alexander Neundorf, <neundorf@kde.org>
# Copyright 2004-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
include(CMakeParseArguments)
function(WRITE_BASIC_CONFIG_VERSION_FILE _filename)
set(options )
set(oneValueArgs VERSION COMPATIBILITY )
set(multiValueArgs )
cmake_parse_arguments(CVF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(CVF_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown keywords given to WRITE_BASIC_CONFIG_VERSION_FILE(): \"${CVF_UNPARSED_ARGUMENTS}\"")
endif()
foreach(MODULE_PATH ${CMAKE_MODULE_PATH})
if (${MODULE_PATH} MATCHES "compat_2.8.11")
set(CURRENT_MODULE_PATH ${MODULE_PATH})
endif()
endforeach()
set(versionTemplateFile "${CURRENT_MODULE_PATH}/BasicConfigVersion-${CVF_COMPATIBILITY}.cmake.in")
if(NOT EXISTS "${versionTemplateFile}")
message(FATAL_ERROR "Bad COMPATIBILITY value used for WRITE_BASIC_CONFIG_VERSION_FILE(): \"${CVF_COMPATIBILITY}\"")
endif()
if("${CVF_VERSION}" STREQUAL "")
message(FATAL_ERROR "No VERSION specified for WRITE_BASIC_CONFIG_VERSION_FILE()")
endif()
configure_file("${versionTemplateFile}" "${_filename}" @ONLY)
endfunction()

View File

@ -24,6 +24,7 @@
#include <freerdp/types.h>
#include <freerdp/update.h>
#include <winpr/wlog.h>
#include <winpr/stream.h>
typedef struct _GLYPH_CACHE GLYPH_CACHE;
@ -56,6 +57,7 @@ struct rdp_glyph_cache
FRAGMENT_CACHE fragCache;
GLYPH_CACHE glyphCache[10];
wLog* log;
rdpContext* context;
rdpSettings* settings;
};

View File

@ -0,0 +1,30 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Audio Input Redirection Virtual Channel
*
* 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 FREERDP_CHANNEL_AUDIN_H
#define FREERDP_CHANNEL_AUDIN_H
#include <freerdp/api.h>
#include <freerdp/dvc.h>
#include <freerdp/types.h>
#endif /* FREERDP_CHANNEL_AUDIN_H */

View File

@ -0,0 +1,29 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Remote Applications Integrated Locally (RAIL)
*
* 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_RAIL_H
#define FREERDP_CHANNEL_RAIL_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#endif /* FREERDP_CHANNEL_RAIL_H */

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