Update upstream source from tag 'upstream/2.3.0+dfsg1'

Update to upstream version '2.3.0+dfsg1'
with Debian dir aaa97caffc
This commit is contained in:
Mike Gabriel 2021-02-25 15:19:16 +01:00
commit 0dc851016e
208 changed files with 11798 additions and 6910 deletions

71
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master, stable* ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master, stable* ]
schedule:
- cron: '30 8 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
# - name: Autobuild
# uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
- run: |
sudo apt update
sudo apt install libxrandr-dev libxinerama-dev libusb-1.0-0-dev xserver-xorg-dev libswscale-dev libswresample-dev libavutil-dev libavcodec-dev libcups2-dev libpulse-dev libasound2-dev libpcsclite-dev xsltproc libxcb-cursor-dev libxcursor-dev libcairo2-dev libfaac-dev libfaad-dev libjpeg-dev libgsm1-dev ninja-build libxfixes-dev libxkbcommon-dev libwayland-dev libpam0g-dev libxdamage-dev libxcb-damage0-dev ccache libxtst-dev libfuse-dev libsystemd-dev libcairo2-dev libsoxr-dev
mkdir ci-build
cd ci-build
cmake -GNinja ../ci/cmake-preloads/config-linux-all.txt ..
cmake --build .
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@ -43,12 +43,15 @@ addons:
- libavutil-dev
- libx264-dev
- libxext-dev
- ninja-build
- libsystemd-dev
- libwayland-dev
before_script:
- ulimit -c unlimited -S
script:
- sudo hostname travis-ci.local
- cmake -G "Unix Makefiles" -C ci/cmake-preloads/config-linux-all.txt -D CMAKE_BUILD_TYPE=Debug -DWITH_LIBSYSTEMD=OFF -DWITH_WAYLAND=OFF .
- cmake -G Ninja -C ci/cmake-preloads/config-linux-all.txt -D CMAKE_BUILD_TYPE=Debug .
- make
- make test

View File

@ -81,7 +81,7 @@ if ($ENV{BUILD_NUMBER})
endif()
set(WITH_LIBRARY_VERSIONING "ON")
set(RAW_VERSION_STRING "2.2.0")
set(RAW_VERSION_STRING "2.3.0")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)
@ -949,15 +949,14 @@ else()
set(FREERDP_PROXY_PLUGINDIR "${PROXY_PLUGINDIR}")
endif()
# Declare we have config.h, generated later on.
add_definitions("-DHAVE_CONFIG_H")
# Include directories
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Configure files
add_definitions("-DHAVE_CONFIG_H")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
# RPATH configuration
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
@ -1073,6 +1072,9 @@ if(WITH_SERVER)
add_subdirectory(server)
endif()
# Configure files - Add last so all symbols are defined
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
# Packaging
set(CMAKE_CPACK_INCLUDE_FILE "CMakeCPack.cmake")

View File

@ -1,3 +1,38 @@
# 2021-02-24 Version 2.3.0
Important notes:
* CMake option WITH_PROXY_MODULES is currently experimental, do not use in
production.
* The clipboard struct FILEDESCRIPTOR was replaced by FILEDESCRIPTORW with
proper data types. They are binary compatible and the former is kept for
compatibility but compilers will emit warnings.
Noteworthy changes:
* Websocket support for proxy connections
* Progressive codec improvements. Reduces graphical glitches against windows
and ogon servers
* Fixed +glyph-cache, now working properly without disconnects
* Huge file support in clipboard
* XWayland support for xfreerdp (keyboard grabbing)
* Improved wlfreerdp (wayland client)
* Option to allow keyboard scancodes to be remapped manually
* Improved mouse wheel behaviour when scrolling
* Improved dynamic channel behaviour, more stable event detection
* New connection state PubSub notification: Clients can now monitor current
connection state
Fixed issues:
* #6626: Fixed parsing of FastGlyph order.
* #6624: Added support for xwayland keyboard grab
* #6492: Added clipboard CB_HUGE_FILE_SUPPORT_ENABLED flag
* #6428: Improve NLA error code logging.
* #6416: Http gateway message support
* #6753: List of pull requests to backport for stable-next
For a complete and detailed change log since the last release run:
git log 2.2.0..2.3.0
# 2020-07-20 Version 2.2.0
Important notes:

View File

@ -39,6 +39,7 @@
#include <winpr/stream.h>
#include <freerdp/freerdp.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/channels/audin.h>
#include "audin_main.h"
@ -102,6 +103,8 @@ struct _AUDIN_PLUGIN
wLog* log;
IWTSListener* listener;
BOOL initialized;
};
static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args);
@ -668,6 +671,7 @@ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
*/
static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{
UINT rc;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin;
if (!audin)
@ -676,6 +680,12 @@ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
if (!pChannelMgr)
return ERROR_INVALID_PARAMETER;
if (audin->initialized)
{
WLog_ERR(TAG, "[%s] channel initialized twice, aborting", AUDIN_DVC_CHANNEL_NAME);
return ERROR_INVALID_DATA;
}
WLog_Print(audin->log, WLOG_TRACE, "...");
audin->listener_callback = (AUDIN_LISTENER_CALLBACK*)calloc(1, sizeof(AUDIN_LISTENER_CALLBACK));
@ -688,8 +698,11 @@ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
audin->listener_callback->iface.OnNewChannelConnection = audin_on_new_channel_connection;
audin->listener_callback->plugin = pPlugin;
audin->listener_callback->channel_mgr = pChannelMgr;
return pChannelMgr->CreateListener(pChannelMgr, "AUDIO_INPUT", 0,
&audin->listener_callback->iface, &audin->listener);
rc = pChannelMgr->CreateListener(pChannelMgr, AUDIN_DVC_CHANNEL_NAME, 0,
&audin->listener_callback->iface, &audin->listener);
audin->initialized = rc == CHANNEL_RC_OK;
return rc;
}
/**

View File

@ -18,17 +18,18 @@
define_channel_client_subsystem("audin" "mac" "")
FIND_LIBRARY(CORE_AUDIO CoreAudio)
FIND_LIBRARY(AVFOUNDATION AVFoundation)
FIND_LIBRARY(AUDIO_TOOL AudioToolbox)
FIND_LIBRARY(APP_SERVICES ApplicationServices)
set(${MODULE_PREFIX}_SRCS
audin_mac.c)
audin_mac.m)
include_directories(..)
include_directories(${MAC_INCLUDE_DIRS})
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
set(${MODULE_PREFIX}_LIBS freerdp ${CORE_AUDIO} ${AUDIO_TOOL} ${APP_SERVICES} winpr)
set(${MODULE_PREFIX}_LIBS freerdp ${AVFOUNDATION} ${CORE_AUDIO} ${AUDIO_TOOL} ${APP_SERVICES} winpr)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})

View File

@ -33,12 +33,14 @@
#include <winpr/debug.h>
#include <winpr/cmdline.h>
#import <AVFoundation/AVFoundation.h>
#define __COREFOUNDATION_CFPLUGINCOM__ 1
#define IUNKNOWN_C_GUTS \
void* _reserved; \
void* QueryInterface; \
void* AddRef; \
void* Release
void *_reserved; \
void *QueryInterface; \
void *AddRef; \
void *Release
#include <CoreAudio/CoreAudioTypes.h>
#include <CoreAudio/CoreAudio.h>
@ -72,17 +74,18 @@ typedef struct _AudinMacDevice
int dev_unit;
AudinReceive receive;
void* user_data;
void *user_data;
rdpContext* rdpcontext;
rdpContext *rdpcontext;
bool isAuthorized;
bool isOpen;
AudioQueueRef audioQueue;
AudioStreamBasicDescription audioFormat;
AudioQueueBufferRef audioBuffers[MAC_AUDIO_QUEUE_NUM_BUFFERS];
} AudinMacDevice;
static AudioFormatID audin_mac_get_format(const AUDIO_FORMAT* format)
static AudioFormatID audin_mac_get_format(const AUDIO_FORMAT *format)
{
switch (format->wFormatTag)
{
@ -94,7 +97,7 @@ static AudioFormatID audin_mac_get_format(const AUDIO_FORMAT* format)
}
}
static AudioFormatFlags audin_mac_get_flags_for_format(const AUDIO_FORMAT* format)
static AudioFormatFlags audin_mac_get_flags_for_format(const AUDIO_FORMAT *format)
{
switch (format->wFormatTag)
{
@ -106,10 +109,14 @@ static AudioFormatFlags audin_mac_get_flags_for_format(const AUDIO_FORMAT* forma
}
}
static BOOL audin_mac_format_supported(IAudinDevice* device, const AUDIO_FORMAT* format)
static BOOL audin_mac_format_supported(IAudinDevice *device, const AUDIO_FORMAT *format)
{
AudinMacDevice *mac = (AudinMacDevice *)device;
AudioFormatID req_fmt = 0;
if (!mac->isAuthorized)
return FALSE;
if (device == NULL || format == NULL)
return FALSE;
@ -126,10 +133,13 @@ static BOOL audin_mac_format_supported(IAudinDevice* device, const AUDIO_FORMAT*
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT audin_mac_set_format(IAudinDevice* device, const AUDIO_FORMAT* format,
static UINT audin_mac_set_format(IAudinDevice *device, const AUDIO_FORMAT *format,
UINT32 FramesPerPacket)
{
AudinMacDevice* mac = (AudinMacDevice*)device;
AudinMacDevice *mac = (AudinMacDevice *)device;
if (!mac->isAuthorized)
return ERROR_INTERNAL_ERROR;
if (device == NULL || format == NULL)
return ERROR_INVALID_PARAMETER;
@ -155,13 +165,13 @@ static UINT audin_mac_set_format(IAudinDevice* device, const AUDIO_FORMAT* forma
return CHANNEL_RC_OK;
}
static void mac_audio_queue_input_cb(void* aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer,
const AudioTimeStamp* inStartTime, UInt32 inNumPackets,
const AudioStreamPacketDescription* inPacketDesc)
static void mac_audio_queue_input_cb(void *aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime, UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDesc)
{
AudinMacDevice* mac = (AudinMacDevice*)aqData;
AudinMacDevice *mac = (AudinMacDevice *)aqData;
UINT error = CHANNEL_RC_OK;
const BYTE* buffer = inBuffer->mAudioData;
const BYTE *buffer = inBuffer->mAudioData;
int buffer_size = inBuffer->mAudioDataByteSize;
(void)inAQ;
(void)inStartTime;
@ -180,12 +190,15 @@ static void mac_audio_queue_input_cb(void* aqData, AudioQueueRef inAQ, AudioQueu
}
}
static UINT audin_mac_close(IAudinDevice* device)
static UINT audin_mac_close(IAudinDevice *device)
{
UINT errCode = CHANNEL_RC_OK;
char errString[1024];
OSStatus devStat;
AudinMacDevice* mac = (AudinMacDevice*)device;
AudinMacDevice *mac = (AudinMacDevice *)device;
if (!mac->isAuthorized)
return ERROR_INTERNAL_ERROR;
if (device == NULL)
return ERROR_INVALID_PARAMETER;
@ -223,13 +236,17 @@ static UINT audin_mac_close(IAudinDevice* device)
return errCode;
}
static UINT audin_mac_open(IAudinDevice* device, AudinReceive receive, void* user_data)
static UINT audin_mac_open(IAudinDevice *device, AudinReceive receive, void *user_data)
{
AudinMacDevice* mac = (AudinMacDevice*)device;
AudinMacDevice *mac = (AudinMacDevice *)device;
DWORD errCode;
char errString[1024];
OSStatus devStat;
size_t index;
if (!mac->isAuthorized)
return ERROR_INTERNAL_ERROR;
mac->receive = receive;
mac->user_data = user_data;
devStat = AudioQueueNewInput(&(mac->audioFormat), mac_audio_queue_input_cb, mac, NULL,
@ -285,9 +302,9 @@ err_out:
return CHANNEL_RC_INITIALIZATION_ERROR;
}
static UINT audin_mac_free(IAudinDevice* device)
static UINT audin_mac_free(IAudinDevice *device)
{
AudinMacDevice* mac = (AudinMacDevice*)device;
AudinMacDevice *mac = (AudinMacDevice *)device;
int error;
if (device == NULL)
@ -302,19 +319,19 @@ static UINT audin_mac_free(IAudinDevice* device)
return CHANNEL_RC_OK;
}
static UINT audin_mac_parse_addin_args(AudinMacDevice* device, ADDIN_ARGV* args)
static UINT audin_mac_parse_addin_args(AudinMacDevice *device, ADDIN_ARGV *args)
{
DWORD errCode;
char errString[1024];
int status;
char *str_num, *eptr;
DWORD flags;
COMMAND_LINE_ARGUMENT_A* arg;
COMMAND_LINE_ARGUMENT_A *arg;
COMMAND_LINE_ARGUMENT_A audin_mac_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>",
NULL, NULL, -1, NULL, "audio device name" },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } };
AudinMacDevice* mac = (AudinMacDevice*)device;
AudinMacDevice *mac = (AudinMacDevice *)device;
if (args->argc == 1)
return CHANNEL_RC_OK;
@ -369,10 +386,10 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
{
DWORD errCode;
char errString[1024];
ADDIN_ARGV* args;
AudinMacDevice* mac;
ADDIN_ARGV *args;
AudinMacDevice *mac;
UINT error;
mac = (AudinMacDevice*)calloc(1, sizeof(AudinMacDevice));
mac = (AudinMacDevice *)calloc(1, sizeof(AudinMacDevice));
if (!mac)
{
@ -397,12 +414,40 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
goto error_out;
}
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)mac)))
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice *)mac)))
{
WLog_ERR(TAG, "RegisterAudinDevice failed with error %" PRIu32 "!", error);
goto error_out;
}
AVAuthorizationStatus status =
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
switch (status)
{
case AVAuthorizationStatusAuthorized:
mac->isAuthorized = TRUE;
break;
case AVAuthorizationStatusNotDetermined:
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio
completionHandler:^(BOOL granted) {
if (granted == YES)
{
mac->isAuthorized = TRUE;
}
else
WLog_WARN(TAG, "Microphone access denied by user");
}];
break;
case AVAuthorizationStatusRestricted:
WLog_WARN(TAG, "Microphone access restricted by policy");
break;
case AVAuthorizationStatusDenied:
WLog_WARN(TAG, "Microphone access denied by policy");
break;
default:
break;
}
return CHANNEL_RC_OK;
error_out:
free(mac);

View File

@ -35,6 +35,7 @@
#include <freerdp/codec/dsp.h>
#include <freerdp/codec/audio.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/channels/audin.h>
#include <freerdp/server/audin.h>
#include <freerdp/channels/log.h>
@ -567,8 +568,8 @@ static BOOL audin_server_open(audin_server_context* context)
WTSFreeMemory(pSessionId);
}
audin->audin_channel =
WTSVirtualChannelOpenEx(audin->SessionId, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
audin->audin_channel = WTSVirtualChannelOpenEx(audin->SessionId, AUDIN_DVC_CHANNEL_NAME,
WTS_CHANNEL_OPTION_DYNAMIC);
if (!audin->audin_channel)
{

View File

@ -206,7 +206,7 @@ static FILETIME uint64_to_filetime(UINT64 value)
* @returns 0 on success, otherwise a Win32 error code.
*/
UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length,
FILEDESCRIPTOR** file_descriptor_array, UINT32* file_descriptor_count)
FILEDESCRIPTORW** file_descriptor_array, UINT32* file_descriptor_count)
{
UINT result = NO_ERROR;
UINT32 i;
@ -240,7 +240,7 @@ UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length,
}
*file_descriptor_count = count;
*file_descriptor_array = calloc(count, sizeof(FILEDESCRIPTOR));
*file_descriptor_array = calloc(count, sizeof(FILEDESCRIPTORW));
if (!*file_descriptor_array)
{
result = ERROR_NOT_ENOUGH_MEMORY;
@ -251,7 +251,7 @@ UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length,
{
int c;
UINT64 lastWriteTime;
FILEDESCRIPTOR* file = &((*file_descriptor_array)[i]);
FILEDESCRIPTORW* file = &((*file_descriptor_array)[i]);
Stream_Read_UINT32(s, file->dwFlags); /* flags (4 bytes) */
Stream_Seek(s, 32); /* reserved1 (32 bytes) */
@ -288,9 +288,17 @@ out:
*
* @returns 0 on success, otherwise a Win32 error code.
*/
UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array,
UINT cliprdr_serialize_file_list(const FILEDESCRIPTORW* file_descriptor_array,
UINT32 file_descriptor_count, BYTE** format_data,
UINT32* format_data_length)
{
return cliprdr_serialize_file_list_ex(CB_STREAM_FILECLIP_ENABLED, file_descriptor_array,
file_descriptor_count, format_data, format_data_length);
}
UINT cliprdr_serialize_file_list_ex(UINT32 flags, const FILEDESCRIPTORW* file_descriptor_array,
UINT32 file_descriptor_count, BYTE** format_data,
UINT32* format_data_length)
{
UINT result = NO_ERROR;
UINT32 i;
@ -299,6 +307,12 @@ UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array,
if (!file_descriptor_array || !format_data || !format_data_length)
return ERROR_BAD_ARGUMENTS;
if ((flags & CB_STREAM_FILECLIP_ENABLED) == 0)
{
WLog_WARN(TAG, "No file clipboard support annouonced!");
return ERROR_BAD_ARGUMENTS;
}
s = Stream_New(NULL, 4 + file_descriptor_count * CLIPRDR_FILEDESCRIPTOR_SIZE);
if (!s)
return ERROR_NOT_ENOUGH_MEMORY;
@ -309,7 +323,7 @@ UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array,
{
int c;
UINT64 lastWriteTime;
const FILEDESCRIPTOR* file = &file_descriptor_array[i];
const FILEDESCRIPTORW* file = &file_descriptor_array[i];
/*
* There is a known issue with Windows server getting stuck in
@ -318,11 +332,14 @@ UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array,
*
* https://support.microsoft.com/en-us/help/2258090
*/
if ((file->nFileSizeHigh > 0) || (file->nFileSizeLow >= CLIPRDR_MAX_FILE_SIZE))
if ((flags & CB_HUGE_FILE_SUPPORT_ENABLED) == 0)
{
WLog_ERR(TAG, "cliprdr does not support files over 2 GB");
result = ERROR_FILE_TOO_LARGE;
goto error;
if ((file->nFileSizeHigh > 0) || (file->nFileSizeLow >= CLIPRDR_MAX_FILE_SIZE))
{
WLog_ERR(TAG, "cliprdr does not support files over 2 GB");
result = ERROR_FILE_TOO_LARGE;
goto error;
}
}
Stream_Write_UINT32(s, file->dwFlags); /* flags (4 bytes) */

View File

@ -36,18 +36,36 @@
#include "../cliprdr_common.h"
#ifdef WITH_DEBUG_CLIPRDR
static const char* const CB_MSG_TYPE_STRINGS[] = { "",
"CB_MONITOR_READY",
"CB_FORMAT_LIST",
"CB_FORMAT_LIST_RESPONSE",
"CB_FORMAT_DATA_REQUEST",
"CB_FORMAT_DATA_RESPONSE",
"CB_TEMP_DIRECTORY",
"CB_CLIP_CAPS",
"CB_FILECONTENTS_REQUEST",
"CB_FILECONTENTS_RESPONSE",
"CB_LOCK_CLIPDATA",
"CB_UNLOCK_CLIPDATA" };
static const char* CB_MSG_TYPE_STRINGS(UINT32 type)
{
switch (type)
{
case CB_MONITOR_READY:
return "CB_MONITOR_READY";
case CB_FORMAT_LIST:
return "CB_FORMAT_LIST";
case CB_FORMAT_LIST_RESPONSE:
return "CB_FORMAT_LIST_RESPONSE";
case CB_FORMAT_DATA_REQUEST:
return "CB_FORMAT_DATA_REQUEST";
case CB_FORMAT_DATA_RESPONSE:
return "CB_FORMAT_DATA_RESPONSE";
case CB_TEMP_DIRECTORY:
return "CB_TEMP_DIRECTORY";
case CB_CLIP_CAPS:
return "CB_CLIP_CAPS";
case CB_FILECONTENTS_REQUEST:
return "CB_FILECONTENTS_REQUEST";
case CB_FILECONTENTS_RESPONSE:
return "CB_FILECONTENTS_RESPONSE";
case CB_LOCK_CLIPDATA:
return "CB_LOCK_CLIPDATA";
case CB_UNLOCK_CLIPDATA:
return "CB_UNLOCK_CLIPDATA";
default:
return "UNKNOWN";
}
}
#endif
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr)
@ -119,6 +137,9 @@ static void cliprdr_print_general_capability_flags(UINT32 flags)
if (flags & CB_CAN_LOCK_CLIPDATA)
WLog_INFO(TAG, "\tCB_CAN_LOCK_CLIPDATA");
if (flags & CB_HUGE_FILE_SUPPORT_ENABLED)
WLog_INFO(TAG, "\tCB_HUGE_FILE_SUPPORT_ENABLED");
WLog_INFO(TAG, "}");
}
#endif
@ -157,6 +178,7 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
cliprdr->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED);
cliprdr->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS);
cliprdr->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA);
cliprdr->hasHugeFileSupport = (generalFlags & CB_HUGE_FILE_SUPPORT_ENABLED);
cliprdr->capabilitiesReceived = TRUE;
if (!context->custom)
@ -441,7 +463,7 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s)
#ifdef WITH_DEBUG_CLIPRDR
WLog_DBG(TAG, "msgType: %s (%" PRIu16 "), msgFlags: %" PRIu16 " dataLen: %" PRIu32 "",
CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen);
CB_MSG_TYPE_STRINGS(msgType), msgType, msgFlags, dataLen);
winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), dataLen + 8);
#endif
@ -570,12 +592,15 @@ static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
if (!cliprdr->fileClipNoFilePaths)
flags &= ~CB_FILECLIP_NO_FILE_PATHS;
if (!cliprdr->canLockClipData)
flags &= CB_CAN_LOCK_CLIPDATA;
flags &= ~CB_CAN_LOCK_CLIPDATA;
if (!cliprdr->hasHugeFileSupport)
flags &= ~CB_HUGE_FILE_SUPPORT_ENABLED;
cliprdr->useLongFormatNames = flags & CB_USE_LONG_FORMAT_NAMES;
cliprdr->streamFileClipEnabled = flags & CB_STREAM_FILECLIP_ENABLED;
cliprdr->fileClipNoFilePaths = flags & CB_FILECLIP_NO_FILE_PATHS;
cliprdr->canLockClipData = flags & CB_CAN_LOCK_CLIPDATA;
cliprdr->hasHugeFileSupport = flags & CB_HUGE_FILE_SUPPORT_ENABLED;
Stream_Write_UINT32(s, flags); /* generalFlags */
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientCapabilities");
@ -774,6 +799,18 @@ cliprdr_client_file_contents_request(CliprdrClientContext* context,
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle;
if (!cliprdr)
return ERROR_INTERNAL_ERROR;
if (!cliprdr->hasHugeFileSupport)
{
if (((UINT64)fileContentsRequest->cbRequested + fileContentsRequest->nPositionLow) >
UINT32_MAX)
return ERROR_INVALID_PARAMETER;
if (fileContentsRequest->nPositionHigh != 0)
return ERROR_INVALID_PARAMETER;
}
s = cliprdr_packet_file_contents_request_new(fileContentsRequest);
if (!s)

View File

@ -49,6 +49,7 @@ struct cliprdr_plugin
BOOL streamFileClipEnabled;
BOOL fileClipNoFilePaths;
BOOL canLockClipData;
BOOL hasHugeFileSupport;
};
typedef struct cliprdr_plugin cliprdrPlugin;

View File

@ -191,6 +191,7 @@ wStream* cliprdr_packet_format_list_new(const CLIPRDR_FORMAT_LIST* formatList,
WCHAR* wszFormatName;
BOOL asciiNames = FALSE;
CLIPRDR_FORMAT* format;
UINT32 length;
if (formatList->msgType != CB_FORMAT_LIST)
WLog_WARN(TAG, "[%s] called with invalid type %08" PRIx32, __FUNCTION__,
@ -198,7 +199,7 @@ wStream* cliprdr_packet_format_list_new(const CLIPRDR_FORMAT_LIST* formatList,
if (!useLongFormatNames)
{
UINT32 length = formatList->numFormats * 36;
length = formatList->numFormats * 36;
s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length);
if (!s)
@ -236,7 +237,10 @@ wStream* cliprdr_packet_format_list_new(const CLIPRDR_FORMAT_LIST* formatList,
ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName, 0);
if (formatNameSize < 0)
{
Stream_Free(s, TRUE);
return NULL;
}
if (formatNameSize > 15)
formatNameSize = 15;
@ -254,7 +258,7 @@ wStream* cliprdr_packet_format_list_new(const CLIPRDR_FORMAT_LIST* formatList,
}
else
{
UINT32 length = 0;
length = 0;
for (index = 0; index < formatList->numFormats; index++)
{
format = (CLIPRDR_FORMAT*)&(formatList->formats[index]);
@ -290,7 +294,10 @@ wStream* cliprdr_packet_format_list_new(const CLIPRDR_FORMAT_LIST* formatList,
const size_t pos = Stream_GetPosition(s);
const size_t rem = cap - pos;
if ((cap < pos) || ((rem / 2) > INT_MAX))
{
Stream_Free(s, TRUE);
return NULL;
}
lpWideCharStr = (LPWSTR)Stream_Pointer(s);
cchWideChar = (int)(rem / 2);
@ -298,7 +305,10 @@ wStream* cliprdr_packet_format_list_new(const CLIPRDR_FORMAT_LIST* formatList,
lpWideCharStr, cchWideChar) *
2;
if (formatNameSize < 0)
{
Stream_Free(s, TRUE);
return NULL;
}
Stream_Seek(s, (size_t)formatNameSize);
}
else

View File

@ -453,6 +453,10 @@ static UINT cliprdr_server_receive_general_capability(CliprdrServerContext* cont
if (context->canLockClipData)
context->canLockClipData = (cap_set->generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE;
if (context->hasHugeFileSupport)
context->hasHugeFileSupport =
(cap_set->generalFlags & CB_HUGE_FILE_SUPPORT_ENABLED) ? TRUE : FALSE;
return CHANNEL_RC_OK;
}
@ -776,6 +780,13 @@ static UINT cliprdr_server_receive_filecontents_request(CliprdrServerContext* co
if ((error = cliprdr_read_file_contents_request(s, &request)))
return error;
if (!context->hasHugeFileSupport)
{
if (request.nPositionHigh > 0)
return ERROR_INVALID_DATA;
if ((UINT64)request.nPositionLow + request.cbRequested > UINT32_MAX)
return ERROR_INVALID_DATA;
}
IFCALLRET(context->ClientFileContentsRequest, error, context, &request);
if (error)
@ -948,6 +959,9 @@ static UINT cliprdr_server_init(CliprdrServerContext* context)
if (context->canLockClipData)
generalFlags |= CB_CAN_LOCK_CLIPDATA;
if (context->hasHugeFileSupport)
generalFlags |= CB_HUGE_FILE_SUPPORT_ENABLED;
capabilities.msgType = CB_CLIP_CAPS;
capabilities.msgFlags = 0;
capabilities.dataLen = 4 + CB_CAPSTYPE_GENERAL_LEN;

View File

@ -72,6 +72,7 @@ struct _DISP_PLUGIN
UINT32 MaxNumMonitors;
UINT32 MaxMonitorAreaFactorA;
UINT32 MaxMonitorAreaFactorB;
BOOL initialized;
};
typedef struct _DISP_PLUGIN DISP_PLUGIN;
@ -296,6 +297,11 @@ static UINT disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
{
UINT status;
DISP_PLUGIN* disp = (DISP_PLUGIN*)pPlugin;
if (disp->initialized)
{
WLog_ERR(TAG, "[%s] channel initialized twice, aborting", DISP_DVC_CHANNEL_NAME);
return ERROR_INVALID_DATA;
}
disp->listener_callback = (DISP_LISTENER_CALLBACK*)calloc(1, sizeof(DISP_LISTENER_CALLBACK));
if (!disp->listener_callback)
@ -310,6 +316,8 @@ static UINT disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
status = pChannelMgr->CreateListener(pChannelMgr, DISP_DVC_CHANNEL_NAME, 0,
&disp->listener_callback->iface, &(disp->listener));
disp->listener->pInterface = disp->iface.pInterface;
disp->initialized = status == CHANNEL_RC_OK;
return status;
}

View File

@ -30,10 +30,12 @@
#define TAG CHANNELS_TAG("drdynvc.client")
static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId,
BOOL bSendClosePDU);
static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr);
static void dvcman_channel_free(void* channel);
static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const BYTE* data,
UINT32 dataSize);
UINT32 dataSize, BOOL* close);
static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s);
static void dvcman_wtslistener_free(DVCMAN_LISTENER* listener)
@ -415,7 +417,7 @@ static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChan
*/
static UINT dvcman_init(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr)
{
size_t i;
int i;
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
UINT error = CHANNEL_RC_OK;
@ -446,6 +448,7 @@ fail:
static UINT dvcman_write_channel(IWTSVirtualChannel* pChannel, ULONG cbSize, const BYTE* pBuffer,
void* pReserved)
{
BOOL close = FALSE;
UINT status;
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)pChannel;
@ -454,8 +457,12 @@ static UINT dvcman_write_channel(IWTSVirtualChannel* pChannel, ULONG cbSize, con
return CHANNEL_RC_BAD_CHANNEL;
EnterCriticalSection(&(channel->lock));
status = drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
status =
drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize, &close);
LeaveCriticalSection(&(channel->lock));
/* Close delayed, it removes the channel struct */
if (close)
dvcman_close_channel(channel->dvcman->drdynvc->channel_mgr, channel->channel_id, TRUE);
return status;
}
@ -483,7 +490,7 @@ static UINT dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr,
UINT32 ChannelId, const char* ChannelName)
{
size_t i;
int i;
BOOL bAccept;
DVCMAN_CHANNEL* channel;
DrdynvcClientContext* context;
@ -602,8 +609,8 @@ static UINT dvcman_open_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelManage
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId,
BOOL bSendClosePDU)
UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId,
BOOL bSendClosePDU)
{
DVCMAN_CHANNEL* channel;
UINT error = CHANNEL_RC_OK;
@ -802,7 +809,7 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s)
* @return 0 on success, otherwise a Win32 error code
*/
static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const BYTE* data,
UINT32 dataSize)
UINT32 dataSize, BOOL* close)
{
wStream* data_out;
size_t pos;
@ -833,7 +840,7 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const B
if (dataSize == 0)
{
dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE);
*close = TRUE;
Stream_Release(data_out);
}
else if (dataSize <= CHANNEL_CHUNK_LENGTH - pos)
@ -1393,15 +1400,23 @@ static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg)
/* Disconnect remaining dynamic channels that the server did not.
* This is required to properly shut down channels by calling the appropriate
* event handlers. */
size_t count = 0;
DVCMAN* drdynvcMgr = (DVCMAN*)drdynvc->channel_mgr;
while (ArrayList_Count(drdynvcMgr->channels) > 0)
do
{
IWTSVirtualChannel* channel =
(IWTSVirtualChannel*)ArrayList_GetItem(drdynvcMgr->channels, 0);
const UINT32 ChannelId = drdynvc->channel_mgr->GetChannelId(channel);
dvcman_close_channel(drdynvc->channel_mgr, ChannelId, FALSE);
}
ArrayList_Lock(drdynvcMgr->channels);
count = ArrayList_Count(drdynvcMgr->channels);
if (count > 0)
{
IWTSVirtualChannel* channel =
(IWTSVirtualChannel*)ArrayList_GetItem(drdynvcMgr->channels, 0);
const UINT32 ChannelId = drdynvc->channel_mgr->GetChannelId(channel);
dvcman_close_channel(drdynvc->channel_mgr, ChannelId, FALSE);
count--;
}
ArrayList_Unlock(drdynvcMgr->channels);
} while (count > 0);
}
if (error && drdynvc->rdpcontext)
@ -1606,7 +1621,7 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
static UINT drdynvc_virtual_channel_event_attached(drdynvcPlugin* drdynvc)
{
UINT error = CHANNEL_RC_OK;
size_t i;
int i;
DVCMAN* dvcman;
if (!drdynvc)
@ -1638,7 +1653,7 @@ fail:
static UINT drdynvc_virtual_channel_event_detached(drdynvcPlugin* drdynvc)
{
UINT error = CHANNEL_RC_OK;
size_t i;
int i;
DVCMAN* dvcman;
if (!drdynvc)

View File

@ -31,6 +31,7 @@
#include "echo_main.h"
#include <freerdp/channels/log.h>
#include <freerdp/channels/echo.h>
#define TAG CHANNELS_TAG("echo.client")
@ -60,6 +61,7 @@ struct _ECHO_PLUGIN
ECHO_LISTENER_CALLBACK* listener_callback;
IWTSListener* listener;
BOOL initialized;
};
/**
@ -129,8 +131,13 @@ static UINT echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallba
*/
static UINT echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{
UINT status;
ECHO_PLUGIN* echo = (ECHO_PLUGIN*)pPlugin;
if (echo->initialized)
{
WLog_ERR(TAG, "[%s] channel initialized twice, aborting", ECHO_DVC_CHANNEL_NAME);
return ERROR_INVALID_DATA;
}
echo->listener_callback = (ECHO_LISTENER_CALLBACK*)calloc(1, sizeof(ECHO_LISTENER_CALLBACK));
if (!echo->listener_callback)
@ -143,8 +150,11 @@ static UINT echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
echo->listener_callback->plugin = pPlugin;
echo->listener_callback->channel_mgr = pChannelMgr;
return pChannelMgr->CreateListener(pChannelMgr, "ECHO", 0, &echo->listener_callback->iface,
&echo->listener);
status = pChannelMgr->CreateListener(pChannelMgr, ECHO_DVC_CHANNEL_NAME, 0,
&echo->listener_callback->iface, &echo->listener);
echo->initialized = status == CHANNEL_RC_OK;
return status;
}
/**

View File

@ -68,6 +68,7 @@ struct _GEOMETRY_PLUGIN
GEOMETRY_LISTENER_CALLBACK* listener_callback;
GeometryClientContext* context;
BOOL initialized;
};
typedef struct _GEOMETRY_PLUGIN GEOMETRY_PLUGIN;
@ -380,6 +381,11 @@ static UINT geometry_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMa
{
UINT status;
GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*)pPlugin;
if (geometry->initialized)
{
WLog_ERR(TAG, "[%s] channel initialized twice, aborting", GEOMETRY_DVC_CHANNEL_NAME);
return ERROR_INVALID_DATA;
}
geometry->listener_callback =
(GEOMETRY_LISTENER_CALLBACK*)calloc(1, sizeof(GEOMETRY_LISTENER_CALLBACK));
@ -396,6 +402,8 @@ static UINT geometry_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMa
pChannelMgr->CreateListener(pChannelMgr, GEOMETRY_DVC_CHANNEL_NAME, 0,
&geometry->listener_callback->iface, &(geometry->listener));
geometry->listener->pInterface = geometry->iface.pInterface;
geometry->initialized = status == CHANNEL_RC_OK;
return status;
}

View File

@ -580,14 +580,6 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
#else
#include <mntent.h>
#define MAX_USB_DEVICES 100
typedef struct _hotplug_dev
{
char* path;
BOOL to_add;
} hotplug_dev;
static const char* automountLocations[] = { "/run/user/%lu/gvfs", "/run/media/%s", "/media/%s",
"/media", "/mnt" };
@ -645,6 +637,143 @@ static BOOL isAutomountLocation(const char* path)
return FALSE;
}
#define MAX_USB_DEVICES 100
typedef struct _hotplug_dev
{
char* path;
BOOL to_add;
} hotplug_dev;
static void handle_mountpoint(hotplug_dev* dev_array, size_t* size, const char* mountpoint)
{
if (!mountpoint)
return;
/* copy hotpluged device mount point to the dev_array */
if (isAutomountLocation(mountpoint) && (*size < MAX_USB_DEVICES))
{
dev_array[*size].path = _strdup(mountpoint);
dev_array[*size + 1].to_add = TRUE;
(*size)++;
}
}
#ifdef __sun
#include <sys/mnttab.h>
static UINT handle_platform_mounts_sun(hotplug_dev* dev_array, size_t* size)
{
FILE* f;
struct mnttab ent;
f = fopen("/etc/mnttab", "r");
if (f == NULL)
{
WLog_ERR(TAG, "fopen failed!");
return ERROR_OPEN_FAILED;
}
while (getmntent(f, &ent) == 0)
{
handle_mountpoint(dev_array, size, ent.mnt_mountp);
}
fclose(f);
return ERROR_SUCCESS;
}
#endif
#if defined(__FreeBSD__) || defined(__OpenBSD__)
#include <sys/mount.h>
static UINT handle_platform_mounts_bsd(hotplug_dev* dev_array, size_t* size)
{
int mntsize;
size_t idx;
struct statfs* mntbuf = NULL;
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
if (!mntsize)
{
/* TODO: handle 'errno' */
WLog_ERR(TAG, "getmntinfo failed!");
return ERROR_OPEN_FAILED;
}
for (idx = 0; idx < (size_t)mntsize; idx++)
{
handle_mountpoint(dev_array, size, mntbuf[idx].f_mntonname);
}
free(mntbuf);
return ERROR_SUCCESS;
}
#endif
#if defined(__LINUX__) || defined(__linux__)
#include <mntent.h>
static UINT handle_platform_mounts_linux(hotplug_dev* dev_array, size_t* size)
{
FILE* f;
struct mntent* ent;
f = fopen("/proc/mounts", "r");
if (f == NULL)
{
WLog_ERR(TAG, "fopen failed!");
return ERROR_OPEN_FAILED;
}
while ((ent = getmntent(f)) != NULL)
{
handle_mountpoint(dev_array, size, ent->mnt_dir);
}
fclose(f);
return ERROR_SUCCESS;
}
#endif
static UINT handle_platform_mounts(hotplug_dev* dev_array, size_t* size)
{
#ifdef __sun
return handle_platform_mounts_sun(dev_array, size);
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
return handle_platform_mounts_bsd(dev_array, size);
#elif defined(__LINUX__) || defined(__linux__)
return handle_platform_mounts_linux(dev_array, size);
#endif
return ERROR_CALL_NOT_IMPLEMENTED;
}
static BOOL device_already_plugged(rdpdrPlugin* rdpdr, const hotplug_dev* device)
{
BOOL rc = FALSE;
int count, x;
ULONG_PTR* keys = NULL;
WCHAR* path = NULL;
int status;
if (!rdpdr || !device)
return TRUE;
if (!device->to_add)
return TRUE;
status = ConvertToUnicode(CP_UTF8, 0, device->path, -1, &path, 0);
if (status <= 0)
return TRUE;
ListDictionary_Lock(rdpdr->devman->devices);
count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys);
for (x = 0; x < count; x++)
{
DEVICE_DRIVE_EXT* device_ext =
(DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue(rdpdr->devman->devices, (void*)keys[x]);
if (!device_ext || (device_ext->device.type != RDPDR_DTYP_FILESYSTEM) || !device_ext->path)
continue;
if (_wcscmp(device_ext->path, path) == 0)
{
rc = TRUE;
break;
}
}
free(keys);
free(path);
ListDictionary_Unlock(rdpdr->devman->devices);
return rc;
}
/**
* Function description
*
@ -652,39 +781,16 @@ static BOOL isAutomountLocation(const char* path)
*/
static UINT handle_hotplug(rdpdrPlugin* rdpdr)
{
FILE* f;
hotplug_dev dev_array[MAX_USB_DEVICES] = { 0 };
size_t i;
size_t size = 0;
int count, j;
struct mntent* ent;
ULONG_PTR* keys = NULL;
UINT32 ids[1];
UINT error = 0;
UINT error = ERROR_SUCCESS;
f = fopen("/proc/mounts", "r");
error = handle_platform_mounts(dev_array, &size);
if (f == NULL)
{
WLog_ERR(TAG, "fopen failed!");
return ERROR_OPEN_FAILED;
}
while ((ent = getmntent(f)) != NULL)
{
/* Copy the line, path must obviously be shorter */
const char* path = ent->mnt_dir;
if (!path)
continue;
/* copy hotpluged device mount point to the dev_array */
if (isAutomountLocation(path) && (size < MAX_USB_DEVICES))
{
dev_array[size].path = _strdup(path);
dev_array[size++].to_add = TRUE;
}
}
fclose(f);
/* delete removed devices */
count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys);
@ -738,7 +844,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr)
/* add new devices */
for (i = 0; i < size; i++)
{
if (dev_array[i].to_add)
if (!device_already_plugged(rdpdr, &dev_array[i]))
{
RDPDR_DRIVE drive = { 0 };
char* name;

File diff suppressed because it is too large Load Diff

View File

@ -34,11 +34,6 @@
#define TAG CHANNELS_TAG("rdpei.client")
#define RDPINPUT_CONTACT_STATE_INITIAL 0x0000
#define RDPINPUT_CONTACT_STATE_ENGAGED 0x0001
#define RDPINPUT_CONTACT_STATE_HOVERING 0x0002
#define RDPINPUT_CONTACT_STATE_OUT_OF_RANGE 0x0003
/**
* Touch Contact State Transitions
*
@ -69,18 +64,23 @@
struct _RDPINPUT_CONTACT_POINT
{
int lastX;
int lastY;
BOOL dirty;
BOOL active;
UINT32 state;
UINT32 flags;
UINT32 contactId;
int externalId;
INT32 externalId;
RDPINPUT_CONTACT_DATA data;
};
typedef struct _RDPINPUT_CONTACT_POINT RDPINPUT_CONTACT_POINT;
struct _RDPINPUT_PEN_CONTACT_POINT
{
BOOL dirty;
BOOL active;
INT32 externalId;
RDPINPUT_PEN_CONTACT data;
};
typedef struct _RDPINPUT_PEN_CONTACT_POINT RDPINPUT_PEN_CONTACT_POINT;
#ifdef WITH_DEBUG_DVC
#define DEBUG_DVC(...) WLog_DBG(TAG, __VA_ARGS__)
#else

View File

@ -27,7 +27,7 @@
#include "rdpei_common.h"
BOOL rdpei_read_2byte_unsigned(wStream* s, UINT32* value)
BOOL rdpei_read_2byte_unsigned(wStream* s, UINT16* value)
{
BYTE byte;
@ -53,10 +53,13 @@ BOOL rdpei_read_2byte_unsigned(wStream* s, UINT32* value)
return TRUE;
}
BOOL rdpei_write_2byte_unsigned(wStream* s, UINT32 value)
BOOL rdpei_write_2byte_unsigned(wStream* s, UINT16 value)
{
BYTE byte;
if (!Stream_EnsureRemainingCapacity(s, 2))
return FALSE;
if (value > 0x7FFF)
return FALSE;
@ -76,7 +79,7 @@ BOOL rdpei_write_2byte_unsigned(wStream* s, UINT32 value)
return TRUE;
}
BOOL rdpei_read_2byte_signed(wStream* s, INT32* value)
BOOL rdpei_read_2byte_signed(wStream* s, INT16* value)
{
BYTE byte;
BOOL negative;
@ -105,11 +108,14 @@ BOOL rdpei_read_2byte_signed(wStream* s, INT32* value)
return TRUE;
}
BOOL rdpei_write_2byte_signed(wStream* s, INT32 value)
BOOL rdpei_write_2byte_signed(wStream* s, INT16 value)
{
BYTE byte;
BOOL negative = FALSE;
if (!Stream_EnsureRemainingCapacity(s, 2))
return FALSE;
if (value < 0)
{
negative = TRUE;
@ -199,6 +205,9 @@ BOOL rdpei_write_4byte_unsigned(wStream* s, UINT32 value)
{
BYTE byte;
if (!Stream_EnsureRemainingCapacity(s, 4))
return FALSE;
if (value <= 0x3FUL)
{
Stream_Write_UINT8(s, value);
@ -300,6 +309,9 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value)
BYTE byte;
BOOL negative = FALSE;
if (!Stream_EnsureRemainingCapacity(s, 4))
return FALSE;
if (value < 0)
{
negative = TRUE;
@ -478,6 +490,9 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
{
BYTE byte;
if (!Stream_EnsureRemainingCapacity(s, 8))
return FALSE;
if (value <= 0x1FULL)
{
byte = value & 0x1F;
@ -501,7 +516,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
else if (value <= 0x1FFFFFULL)
else if (value <= 0x1FFFFFFFULL)
{
byte = (value >> 24) & 0x1F;
byte |= (3 << 5);
@ -513,7 +528,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
else if (value <= 0x1FFFFFFFULL)
else if (value <= 0x1FFFFFFFFFULL)
{
byte = (value >> 32) & 0x1F;
byte |= (4 << 5);
@ -527,7 +542,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
else if (value <= 0x1FFFFFFFFFULL)
else if (value <= 0x1FFFFFFFFFFFULL)
{
byte = (value >> 40) & 0x1F;
byte |= (5 << 5);
@ -543,7 +558,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
else if (value <= 0x1FFFFFFFFFFFULL)
else if (value <= 0x1FFFFFFFFFFFFFULL)
{
byte = (value >> 48) & 0x1F;
byte |= (6 << 5);
@ -591,7 +606,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
void touch_event_reset(RDPINPUT_TOUCH_EVENT* event)
{
int i;
UINT16 i;
for (i = 0; i < event->frameCount; i++)
touch_frame_reset(&event->frames[i]);
@ -607,3 +622,22 @@ void touch_frame_reset(RDPINPUT_TOUCH_FRAME* frame)
frame->contacts = NULL;
frame->contactCount = 0;
}
void pen_event_reset(RDPINPUT_PEN_EVENT* event)
{
UINT16 i;
for (i = 0; i < event->frameCount; i++)
pen_frame_reset(&event->frames[i]);
free(event->frames);
event->frames = NULL;
event->frameCount = 0;
}
void pen_frame_reset(RDPINPUT_PEN_FRAME* frame)
{
free(frame->contacts);
frame->contacts = NULL;
frame->contactCount = 0;
}

View File

@ -33,13 +33,14 @@ enum
EVENTID_TOUCH = 0x0003,
EVENTID_SUSPEND_TOUCH = 0x0004,
EVENTID_RESUME_TOUCH = 0x0005,
EVENTID_DISMISS_HOVERING_CONTACT = 0x0006
EVENTID_DISMISS_HOVERING_CONTACT = 0x0006,
EVENTID_PEN = 0x0008
};
BOOL rdpei_read_2byte_unsigned(wStream* s, UINT32* value);
BOOL rdpei_write_2byte_unsigned(wStream* s, UINT32 value);
BOOL rdpei_read_2byte_signed(wStream* s, INT32* value);
BOOL rdpei_write_2byte_signed(wStream* s, INT32 value);
BOOL rdpei_read_2byte_unsigned(wStream* s, UINT16* value);
BOOL rdpei_write_2byte_unsigned(wStream* s, UINT16 value);
BOOL rdpei_read_2byte_signed(wStream* s, INT16* value);
BOOL rdpei_write_2byte_signed(wStream* s, INT16 value);
BOOL rdpei_read_4byte_unsigned(wStream* s, UINT32* value);
BOOL rdpei_write_4byte_unsigned(wStream* s, UINT32 value);
BOOL rdpei_read_4byte_signed(wStream* s, INT32* value);
@ -50,4 +51,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value);
void touch_event_reset(RDPINPUT_TOUCH_EVENT* event);
void touch_frame_reset(RDPINPUT_TOUCH_FRAME* frame);
void pen_event_reset(RDPINPUT_PEN_EVENT* event);
void pen_frame_reset(RDPINPUT_PEN_FRAME* frame);
#endif /* FREERDP_CHANNEL_RDPEI_COMMON_H */

View File

@ -55,6 +55,7 @@ struct _rdpei_server_private
UINT16 currentMsgType;
RDPINPUT_TOUCH_EVENT touchEvent;
RDPINPUT_PEN_EVENT penEvent;
enum RdpEiState automataState;
};
@ -69,26 +70,22 @@ RdpeiServerContext* rdpei_server_context_new(HANDLE vcm)
ret->priv = priv = calloc(1, sizeof(*ret->priv));
if (!priv)
goto out_free;
goto fail;
priv->inputStream = Stream_New(NULL, 256);
if (!priv->inputStream)
goto out_free_priv;
goto fail;
priv->outputStream = Stream_New(NULL, 200);
if (!priv->inputStream)
goto out_free_input_stream;
goto fail;
ret->vcm = vcm;
rdpei_server_context_reset(ret);
return ret;
out_free_input_stream:
Stream_Free(priv->inputStream, TRUE);
out_free_priv:
free(ret->priv);
out_free:
free(ret);
fail:
rdpei_server_context_free(ret);
return NULL;
}
@ -145,10 +142,17 @@ void rdpei_server_context_reset(RdpeiServerContext* context)
void rdpei_server_context_free(RdpeiServerContext* context)
{
RdpeiServerPrivate* priv = context->priv;
if (priv->channelHandle != INVALID_HANDLE_VALUE)
WTSVirtualChannelClose(priv->channelHandle);
Stream_Free(priv->inputStream, TRUE);
RdpeiServerPrivate* priv;
if (!context)
return;
priv = context->priv;
if (priv)
{
if (priv->channelHandle != INVALID_HANDLE_VALUE)
WTSVirtualChannelClose(priv->channelHandle);
Stream_Free(priv->inputStream, TRUE);
}
free(priv);
free(context);
}
@ -180,6 +184,8 @@ static UINT read_cs_ready_message(RdpeiServerContext* context, wStream* s)
{
case RDPINPUT_PROTOCOL_V10:
case RDPINPUT_PROTOCOL_V101:
case RDPINPUT_PROTOCOL_V200:
case RDPINPUT_PROTOCOL_V300:
break;
default:
WLog_ERR(TAG, "unhandled RPDEI protocol version 0x%" PRIx32 "", context->clientVersion);
@ -201,6 +207,8 @@ static UINT read_cs_ready_message(RdpeiServerContext* context, wStream* s)
static UINT read_touch_contact_data(RdpeiServerContext* context, wStream* s,
RDPINPUT_CONTACT_DATA* contactData)
{
UINT16 tmp;
WINPR_UNUSED(context);
if (Stream_GetRemainingLength(s) < 1)
{
WLog_ERR(TAG, "Not enough data!");
@ -208,25 +216,28 @@ static UINT read_touch_contact_data(RdpeiServerContext* context, wStream* s,
}
Stream_Read_UINT8(s, contactData->contactId);
if (!rdpei_read_2byte_unsigned(s, &contactData->fieldsPresent) ||
!rdpei_read_4byte_signed(s, &contactData->x) ||
if (!rdpei_read_2byte_unsigned(s, &tmp) || !rdpei_read_4byte_signed(s, &contactData->x) ||
!rdpei_read_4byte_signed(s, &contactData->y) ||
!rdpei_read_4byte_unsigned(s, &contactData->contactFlags))
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
contactData->fieldsPresent = tmp;
if (contactData->fieldsPresent & CONTACT_DATA_CONTACTRECT_PRESENT)
{
if (!rdpei_read_2byte_signed(s, &contactData->contactRectLeft) ||
!rdpei_read_2byte_signed(s, &contactData->contactRectTop) ||
!rdpei_read_2byte_signed(s, &contactData->contactRectRight) ||
!rdpei_read_2byte_signed(s, &contactData->contactRectBottom))
INT16 tmp[4] = { 0 };
if (!rdpei_read_2byte_signed(s, &tmp[0]) || !rdpei_read_2byte_signed(s, &tmp[1]) ||
!rdpei_read_2byte_signed(s, &tmp[2]) || !rdpei_read_2byte_signed(s, &tmp[3]))
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
contactData->contactRectLeft = tmp[0];
contactData->contactRectTop = tmp[1];
contactData->contactRectRight = tmp[2];
contactData->contactRectBottom = tmp[3];
}
if ((contactData->fieldsPresent & CONTACT_DATA_ORIENTATION_PRESENT) &&
@ -246,6 +257,55 @@ static UINT read_touch_contact_data(RdpeiServerContext* context, wStream* s,
return CHANNEL_RC_OK;
}
static UINT read_pen_contact(RdpeiServerContext* context, wStream* s,
RDPINPUT_PEN_CONTACT* contactData)
{
WINPR_UNUSED(context);
if (Stream_GetRemainingLength(s) < 1)
{
WLog_ERR(TAG, "Not enough data!");
return ERROR_INVALID_DATA;
}
Stream_Read_UINT8(s, contactData->deviceId);
if (!rdpei_read_2byte_unsigned(s, &contactData->fieldsPresent) ||
!rdpei_read_4byte_signed(s, &contactData->x) ||
!rdpei_read_4byte_signed(s, &contactData->y) ||
!rdpei_read_4byte_unsigned(s, &contactData->contactFlags))
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
if (contactData->fieldsPresent & PEN_CONTACT_PENFLAGS_PRESENT)
{
if (!rdpei_read_4byte_unsigned(s, &contactData->penFlags))
return ERROR_INVALID_DATA;
}
if (contactData->fieldsPresent & PEN_CONTACT_PRESSURE_PRESENT)
{
if (!rdpei_read_4byte_unsigned(s, &contactData->pressure))
return ERROR_INVALID_DATA;
}
if (contactData->fieldsPresent & PEN_CONTACT_ROTATION_PRESENT)
{
if (!rdpei_read_2byte_unsigned(s, &contactData->rotation))
return ERROR_INVALID_DATA;
}
if (contactData->fieldsPresent & PEN_CONTACT_TILTX_PRESENT)
{
if (!rdpei_read_2byte_signed(s, &contactData->tiltX))
return ERROR_INVALID_DATA;
}
if (contactData->fieldsPresent & PEN_CONTACT_TILTY_PRESENT)
{
if (!rdpei_read_2byte_signed(s, &contactData->tiltY))
return ERROR_INVALID_DATA;
}
return CHANNEL_RC_OK;
}
/**
* Function description
*
@ -254,15 +314,16 @@ static UINT read_touch_contact_data(RdpeiServerContext* context, wStream* s,
static UINT read_touch_frame(RdpeiServerContext* context, wStream* s, RDPINPUT_TOUCH_FRAME* frame)
{
UINT32 i;
UINT16 tmp;
RDPINPUT_CONTACT_DATA* contact;
UINT error;
if (!rdpei_read_2byte_unsigned(s, &frame->contactCount) ||
!rdpei_read_8byte_unsigned(s, &frame->frameOffset))
if (!rdpei_read_2byte_unsigned(s, &tmp) || !rdpei_read_8byte_unsigned(s, &frame->frameOffset))
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
frame->contactCount = tmp;
frame->contacts = contact = calloc(frame->contactCount, sizeof(RDPINPUT_CONTACT_DATA));
if (!frame->contacts)
@ -284,6 +345,39 @@ static UINT read_touch_frame(RdpeiServerContext* context, wStream* s, RDPINPUT_T
return CHANNEL_RC_OK;
}
static UINT read_pen_frame(RdpeiServerContext* context, wStream* s, RDPINPUT_PEN_FRAME* frame)
{
UINT32 i;
RDPINPUT_PEN_CONTACT* contact;
UINT error;
if (!rdpei_read_2byte_unsigned(s, &frame->contactCount) ||
!rdpei_read_8byte_unsigned(s, &frame->frameOffset))
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
frame->contacts = contact = calloc(frame->contactCount, sizeof(RDPINPUT_CONTACT_DATA));
if (!frame->contacts)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
for (i = 0; i < frame->contactCount; i++, contact++)
{
if ((error = read_pen_contact(context, s, contact)))
{
WLog_ERR(TAG, "read_touch_contact_data failed with error %" PRIu32 "!", error);
frame->contactCount = i;
pen_frame_reset(frame);
return error;
}
}
return CHANNEL_RC_OK;
}
/**
* Function description
*
@ -291,7 +385,7 @@ static UINT read_touch_frame(RdpeiServerContext* context, wStream* s, RDPINPUT_T
*/
static UINT read_touch_event(RdpeiServerContext* context, wStream* s)
{
UINT32 frameCount;
UINT16 frameCount;
UINT32 i;
RDPINPUT_TOUCH_EVENT* event = &context->priv->touchEvent;
RDPINPUT_TOUCH_FRAME* frame;
@ -331,6 +425,48 @@ out_cleanup:
return error;
}
static UINT read_pen_event(RdpeiServerContext* context, wStream* s)
{
UINT16 frameCount;
UINT32 i;
RDPINPUT_PEN_EVENT* event = &context->priv->penEvent;
RDPINPUT_PEN_FRAME* frame;
UINT error = CHANNEL_RC_OK;
if (!rdpei_read_4byte_unsigned(s, &event->encodeTime) ||
!rdpei_read_2byte_unsigned(s, &frameCount))
{
WLog_ERR(TAG, "rdpei_read_ failed!");
return ERROR_INTERNAL_ERROR;
}
event->frameCount = frameCount;
event->frames = frame = calloc(event->frameCount, sizeof(RDPINPUT_PEN_FRAME));
if (!event->frames)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
for (i = 0; i < frameCount; i++, frame++)
{
if ((error = read_pen_frame(context, s, frame)))
{
WLog_ERR(TAG, "read_pen_frame failed with error %" PRIu32 "!", error);
event->frameCount = i;
goto out_cleanup;
}
}
IFCALLRET(context->onPenEvent, error, context, event);
if (error)
WLog_ERR(TAG, "context->onPenEvent failed with error %" PRIu32 "", error);
out_cleanup:
pen_event_reset(event);
return error;
}
/**
* Function description
*
@ -445,6 +581,13 @@ UINT rdpei_server_handle_messages(RdpeiServerContext* context)
return error;
}
break;
case EVENTID_PEN:
if ((error = read_pen_event(context, s)))
{
WLog_ERR(TAG, "read_pen_event failed with error %" PRIu32 "", error);
return error;
}
break;
default:
WLog_ERR(TAG, "unexpected message type 0x%" PRIx16 "", priv->currentMsgType);
}
@ -455,12 +598,17 @@ UINT rdpei_server_handle_messages(RdpeiServerContext* context)
return error;
}
UINT rdpei_server_send_sc_ready(RdpeiServerContext* context, UINT32 version)
{
return rdpei_server_send_sc_ready_ex(context, version, 0);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rdpei_server_send_sc_ready(RdpeiServerContext* context, UINT32 version)
UINT rdpei_server_send_sc_ready_ex(RdpeiServerContext* context, UINT32 version, UINT32 features)
{
ULONG written;
RdpeiServerPrivate* priv = context->priv;
@ -482,6 +630,8 @@ UINT rdpei_server_send_sc_ready(RdpeiServerContext* context, UINT32 version)
Stream_Write_UINT16(priv->outputStream, EVENTID_SC_READY);
Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH + 4);
Stream_Write_UINT32(priv->outputStream, version);
if (version >= RDPINPUT_PROTOCOL_V300)
Stream_Write_UINT32(priv->outputStream, features);
if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream),
Stream_GetPosition(priv->outputStream), &written))

View File

@ -1878,6 +1878,11 @@ static UINT rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana
{
UINT error;
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)pPlugin;
if (gfx->initialized)
{
WLog_ERR(TAG, "[%s] channel initialized twice, aborting", RDPGFX_DVC_CHANNEL_NAME);
return ERROR_INVALID_DATA;
}
gfx->listener_callback = (RDPGFX_LISTENER_CALLBACK*)calloc(1, sizeof(RDPGFX_LISTENER_CALLBACK));
if (!gfx->listener_callback)
@ -1893,6 +1898,8 @@ static UINT rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana
&gfx->listener_callback->iface, &(gfx->listener));
gfx->listener->pInterface = gfx->iface.pInterface;
DEBUG_RDPGFX(gfx->log, "Initialize");
gfx->initialized = error == CHANNEL_RC_OK;
return error;
}

View File

@ -85,6 +85,7 @@ struct _RDPGFX_PLUGIN
wLog* log;
RDPGFX_CAPSET ConnectionCaps;
BOOL SendQoeAck;
BOOL initialized;
};
typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN;

View File

@ -129,6 +129,8 @@ UINT rdpgfx_read_header(wStream* s, RDPGFX_HEADER* header)
*/
UINT rdpgfx_write_header(wStream* s, const RDPGFX_HEADER* header)
{
if (!Stream_EnsureRemainingCapacity(s, 8))
return ERROR_INTERNAL_ERROR;
Stream_Write_UINT16(s, header->cmdId); /* cmdId (2 bytes) */
Stream_Write_UINT16(s, header->flags); /* flags (2 bytes) */
Stream_Write_UINT32(s, header->pduLength); /* pduLength (4 bytes) */

View File

@ -72,13 +72,17 @@ static INLINE UINT rdpgfx_server_packet_init_header(wStream* s, UINT16 cmdId, UI
* @param s stream
* @param start saved start pos of the packet in the stream
*/
static INLINE void rdpgfx_server_packet_complete_header(wStream* s, size_t start)
static INLINE BOOL rdpgfx_server_packet_complete_header(wStream* s, size_t start)
{
size_t current = Stream_GetPosition(s);
const size_t current = Stream_GetPosition(s);
const size_t cap = Stream_Capacity(s);
if (cap < start + RDPGFX_HEADER_SIZE)
return FALSE;
/* Fill actual length */
Stream_SetPosition(s, start + RDPGFX_HEADER_SIZE - sizeof(UINT32));
Stream_Write_UINT32(s, current - start); /* pduLength (4 bytes) */
Stream_SetPosition(s, current);
return TRUE;
}
/**
@ -360,15 +364,21 @@ static UINT rdpgfx_send_delete_surface_pdu(RdpgfxServerContext* context,
return rdpgfx_server_single_packet_send(context, s);
}
static INLINE void rdpgfx_write_start_frame_pdu(wStream* s, const RDPGFX_START_FRAME_PDU* pdu)
static INLINE BOOL rdpgfx_write_start_frame_pdu(wStream* s, const RDPGFX_START_FRAME_PDU* pdu)
{
if (!Stream_EnsureRemainingCapacity(s, 8))
return FALSE;
Stream_Write_UINT32(s, pdu->timestamp); /* timestamp (4 bytes) */
Stream_Write_UINT32(s, pdu->frameId); /* frameId (4 bytes) */
return TRUE;
}
static INLINE void rdpgfx_write_end_frame_pdu(wStream* s, const RDPGFX_END_FRAME_PDU* pdu)
static INLINE BOOL rdpgfx_write_end_frame_pdu(wStream* s, const RDPGFX_END_FRAME_PDU* pdu)
{
if (!Stream_EnsureRemainingCapacity(s, 4))
return FALSE;
Stream_Write_UINT32(s, pdu->frameId); /* frameId (4 bytes) */
return TRUE;
}
/**
@ -586,6 +596,8 @@ static UINT rdpgfx_write_surface_command(wStream* s, const RDPGFX_SURFACE_COMMAN
if (cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE ||
cmd->codecId == RDPGFX_CODECID_CAPROGRESSIVE_V2)
{
if (!Stream_EnsureRemainingCapacity(s, 13 + cmd->length))
return ERROR_INTERNAL_ERROR;
/* Write RDPGFX_CMDID_WIRETOSURFACE_2 format for CAPROGRESSIVE */
Stream_Write_UINT16(s, cmd->surfaceId); /* surfaceId (2 bytes) */
Stream_Write_UINT16(s, cmd->codecId); /* codecId (2 bytes) */
@ -597,6 +609,8 @@ static UINT rdpgfx_write_surface_command(wStream* s, const RDPGFX_SURFACE_COMMAN
else
{
/* Write RDPGFX_CMDID_WIRETOSURFACE_1 format for others */
if (!Stream_EnsureRemainingCapacity(s, 17))
return ERROR_INTERNAL_ERROR;
Stream_Write_UINT16(s, cmd->surfaceId); /* surfaceId (2 bytes) */
Stream_Write_UINT16(s, cmd->codecId); /* codecId (2 bytes) */
Stream_Write_UINT8(s, pixelFormat); /* pixelFormat (1 byte) */
@ -623,6 +637,8 @@ static UINT rdpgfx_write_surface_command(wStream* s, const RDPGFX_SURFACE_COMMAN
{
havc444 = (RDPGFX_AVC444_BITMAP_STREAM*)cmd->extra;
havc420 = &(havc444->bitstream[0]); /* avc420EncodedBitstreamInfo (4 bytes) */
if (!Stream_EnsureRemainingCapacity(s, 4))
return ERROR_INTERNAL_ERROR;
Stream_Write_UINT32(s, havc444->cbAvc420EncodedBitstream1 | (havc444->LC << 30UL));
/* avc420EncodedBitstream1 */
error = rdpgfx_write_h264_avc420(s, havc420);
@ -648,14 +664,19 @@ static UINT rdpgfx_write_surface_command(wStream* s, const RDPGFX_SURFACE_COMMAN
}
else
{
if (!Stream_EnsureRemainingCapacity(s, cmd->length))
return ERROR_INTERNAL_ERROR;
Stream_Write(s, cmd->data, cmd->length);
}
/* Fill actual bitmap data length */
bitmapDataLength = Stream_GetPosition(s) - bitmapDataStart;
Stream_SetPosition(s, bitmapDataStart - sizeof(UINT32));
if (!Stream_EnsureRemainingCapacity(s, 4))
return ERROR_INTERNAL_ERROR;
Stream_Write_UINT32(s, bitmapDataLength); /* bitmapDataLength (4 bytes) */
Stream_Seek(s, bitmapDataLength);
if (!Stream_SafeSeek(s, bitmapDataLength))
return ERROR_INTERNAL_ERROR;
}
return error;
@ -745,8 +766,9 @@ static UINT rdpgfx_send_surface_frame_command(RdpgfxServerContext* context,
goto error;
}
rdpgfx_write_start_frame_pdu(s, startFrame);
rdpgfx_server_packet_complete_header(s, position);
if (!rdpgfx_write_start_frame_pdu(s, startFrame) ||
!rdpgfx_server_packet_complete_header(s, position))
goto error;
}
/* Write RDPGFX_CMDID_WIRETOSURFACE_1 or RDPGFX_CMDID_WIRETOSURFACE_2 */
@ -768,7 +790,8 @@ static UINT rdpgfx_send_surface_frame_command(RdpgfxServerContext* context,
goto error;
}
rdpgfx_server_packet_complete_header(s, position);
if (!rdpgfx_server_packet_complete_header(s, position))
goto error;
/* Write end frame if exists */
if (endFrame)
@ -782,8 +805,9 @@ static UINT rdpgfx_send_surface_frame_command(RdpgfxServerContext* context,
goto error;
}
rdpgfx_write_end_frame_pdu(s, endFrame);
rdpgfx_server_packet_complete_header(s, position);
if (!rdpgfx_write_end_frame_pdu(s, endFrame) ||
!rdpgfx_server_packet_complete_header(s, position))
goto error;
}
return rdpgfx_server_packet_send(context, s);

View File

@ -167,22 +167,14 @@ static BOOL rdpsnd_mac_open(rdpsndDevicePlugin *device, const AUDIO_FORMAT *form
if (!mac->engine)
return FALSE;
if (@available(macOS 10.15, *))
err = AudioUnitSetProperty(mac->engine.outputNode.audioUnit,
kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0,
&outputDeviceID, sizeof(outputDeviceID));
if (err)
{
/* Setting the output audio device on 10.15 or later breaks sound playback. Do not set for
* now until we find a proper fix for #5747 */
}
else
{
err = AudioUnitSetProperty(mac->engine.outputNode.audioUnit,
kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global,
0, &outputDeviceID, sizeof(outputDeviceID));
if (err)
{
rdpsnd_mac_release(mac);
WLog_ERR(TAG, "AudioUnitSetProperty: %s", FormatError(err));
return FALSE;
}
rdpsnd_mac_release(mac);
WLog_ERR(TAG, "AudioUnitSetProperty: %s", FormatError(err));
return FALSE;
}
mac->player = [[AVAudioPlayerNode alloc] init];
@ -197,6 +189,8 @@ static BOOL rdpsnd_mac_open(rdpsndDevicePlugin *device, const AUDIO_FORMAT *form
[mac->engine connect:mac->player to:mac->engine.mainMixerNode format:nil];
[mac->engine prepare];
if (![mac->engine startAndReturnError:&error])
{
device->Close(device);
@ -275,6 +269,19 @@ static void rdpsnd_mac_start(rdpsndDevicePlugin *device)
if (!mac->isPlaying)
{
if (!mac->engine.isRunning)
{
NSError *error;
if (![mac->engine startAndReturnError:&error])
{
device->Close(device);
WLog_ERR(TAG, "Failed to start audio player %s",
[error.localizedDescription UTF8String]);
return;
}
}
[mac->player play];
mac->isPlaying = TRUE;

View File

@ -125,6 +125,7 @@ struct rdpsnd_plugin
HANDLE thread;
wMessageQueue* queue;
BOOL initialized;
};
static const char* rdpsnd_is_dyn_str(BOOL dynamic)
@ -494,6 +495,38 @@ static BOOL rdpsnd_detect_overrun(rdpsndPlugin* rdpsnd, const AUDIO_FORMAT* form
if (!rdpsnd || !format)
return FALSE;
/* Older windows RDP servers do not limit the send buffer, which can
* cause quite a large amount of sound data buffered client side.
* If e.g. sound is paused server side the client will keep playing
* for a long time instead of pausing playback.
*
* To avoid this we check:
*
* 1. Is the sound sample received from a known format these servers
* support
* 2. If it is calculate the size of the client side sound buffer
* 3. If the buffer is too large silently drop the sample which will
* trigger a retransmit later on.
*
* This check must only be applied to these known formats, because
* with newer and other formats the sample size can not be calculated
* without decompressing the sample first.
*/
switch (format->wFormatTag)
{
case WAVE_FORMAT_PCM:
case WAVE_FORMAT_DVI_ADPCM:
case WAVE_FORMAT_ADPCM:
case WAVE_FORMAT_ALAW:
case WAVE_FORMAT_MULAW:
break;
case WAVE_FORMAT_MSG723:
case WAVE_FORMAT_GSM610:
case WAVE_FORMAT_AAC_MS:
default:
return FALSE;
}
audio_format_print(WLog_Get(TAG), WLOG_DEBUG, format);
bpf = format->nChannels * format->wBitsPerSample * format->nSamplesPerSec / 8;
if (bpf == 0)
@ -633,9 +666,9 @@ static UINT rdpsnd_recv_wave2_pdu(rdpsndPlugin* rdpsnd, wStream* s, UINT16 BodyS
rdpsnd->waveDataSize = BodySize - 12;
rdpsnd->wArrivalTime = GetTickCount64();
WLog_Print(rdpsnd->log, WLOG_DEBUG,
"%s Wave2PDU: cBlockNo: %" PRIu8 " wFormatNo: %" PRIu16 ", align=%hu",
"%s Wave2PDU: cBlockNo: %" PRIu8 " wFormatNo: %" PRIu16 " [%s] , align=%hu",
rdpsnd_is_dyn_str(rdpsnd->dynamic), rdpsnd->cBlockNo, wFormatNo,
format->nBlockAlign);
audio_format_get_tag_string(format->wFormatTag), format->nBlockAlign);
if (!rdpsnd_ensure_device_is_open(rdpsnd, wFormatNo, format))
return ERROR_INTERNAL_ERROR;
@ -1528,6 +1561,11 @@ static UINT rdpsnd_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana
{
UINT status;
rdpsndPlugin* rdpsnd = (rdpsndPlugin*)pPlugin;
if (rdpsnd->initialized)
{
WLog_ERR(TAG, "[%s] channel initialized twice, aborting", RDPSND_DVC_CHANNEL_NAME);
return ERROR_INVALID_DATA;
}
rdpsnd->listener_callback =
(RDPSND_LISTENER_CALLBACK*)calloc(1, sizeof(RDPSND_LISTENER_CALLBACK));
@ -1543,7 +1581,10 @@ static UINT rdpsnd_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana
status = pChannelMgr->CreateListener(pChannelMgr, RDPSND_DVC_CHANNEL_NAME, 0,
&rdpsnd->listener_callback->iface, &(rdpsnd->listener));
rdpsnd->listener->pInterface = rdpsnd->iface.pInterface;
return rdpsnd_virtual_channel_event_initialized(rdpsnd);
status = rdpsnd_virtual_channel_event_initialized(rdpsnd);
rdpsnd->initialized = status == CHANNEL_RC_OK;
return status;
}
/**

View File

@ -22,6 +22,7 @@ set(${MODULE_PREFIX}_SRCS
smartcard_main.h
smartcard_pack.c
smartcard_pack.h
smartcard_operations.h
smartcard_operations.c)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "DeviceServiceEntry")

View File

@ -209,6 +209,7 @@ static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard)
* Call SCardCancel on existing contexts, unblocking all outstanding SCardGetStatusChange calls.
*/
ListDictionary_Lock(smartcard->rgSCardContextList);
if (ListDictionary_Count(smartcard->rgSCardContextList) > 0)
{
pKeys = NULL;
@ -232,11 +233,17 @@ static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard)
free(pKeys);
}
ListDictionary_Unlock(smartcard->rgSCardContextList);
/* Put thread to sleep so that PC/SC can process the cancel requests. This fixes a race
* condition that sometimes caused the pc/sc daemon to crash on MacOS (_xpc_api_misuse) */
Sleep(100);
/**
* Call SCardReleaseContext on remaining contexts and remove them from rgSCardContextList.
*/
ListDictionary_Lock(smartcard->rgSCardContextList);
if (ListDictionary_Count(smartcard->rgSCardContextList) > 0)
{
pKeys = NULL;
@ -269,6 +276,7 @@ static void smartcard_release_all_contexts(SMARTCARD_DEVICE* smartcard)
free(pKeys);
}
ListDictionary_Unlock(smartcard->rgSCardContextList);
}
static UINT smartcard_free_(SMARTCARD_DEVICE* smartcard)

View File

@ -32,76 +32,12 @@
#include <winpr/smartcard.h>
#include <winpr/collections.h>
#include "smartcard_operations.h"
#define TAG CHANNELS_TAG("smartcard.client")
#define RDP_SCARD_CTL_CODE(code) \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, (code), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SCARD_IOCTL_ESTABLISHCONTEXT RDP_SCARD_CTL_CODE(5) /* SCardEstablishContext */
#define SCARD_IOCTL_RELEASECONTEXT RDP_SCARD_CTL_CODE(6) /* SCardReleaseContext */
#define SCARD_IOCTL_ISVALIDCONTEXT RDP_SCARD_CTL_CODE(7) /* SCardIsValidContext */
#define SCARD_IOCTL_LISTREADERGROUPSA RDP_SCARD_CTL_CODE(8) /* SCardListReaderGroupsA */
#define SCARD_IOCTL_LISTREADERGROUPSW RDP_SCARD_CTL_CODE(9) /* SCardListReaderGroupsW */
#define SCARD_IOCTL_LISTREADERSA RDP_SCARD_CTL_CODE(10) /* SCardListReadersA */
#define SCARD_IOCTL_LISTREADERSW RDP_SCARD_CTL_CODE(11) /* SCardListReadersW */
#define SCARD_IOCTL_INTRODUCEREADERGROUPA RDP_SCARD_CTL_CODE(20) /* SCardIntroduceReaderGroupA */
#define SCARD_IOCTL_INTRODUCEREADERGROUPW RDP_SCARD_CTL_CODE(21) /* SCardIntroduceReaderGroupW */
#define SCARD_IOCTL_FORGETREADERGROUPA RDP_SCARD_CTL_CODE(22) /* SCardForgetReaderGroupA */
#define SCARD_IOCTL_FORGETREADERGROUPW RDP_SCARD_CTL_CODE(23) /* SCardForgetReaderGroupW */
#define SCARD_IOCTL_INTRODUCEREADERA RDP_SCARD_CTL_CODE(24) /* SCardIntroduceReaderA */
#define SCARD_IOCTL_INTRODUCEREADERW RDP_SCARD_CTL_CODE(25) /* SCardIntroduceReaderW */
#define SCARD_IOCTL_FORGETREADERA RDP_SCARD_CTL_CODE(26) /* SCardForgetReaderA */
#define SCARD_IOCTL_FORGETREADERW RDP_SCARD_CTL_CODE(27) /* SCardForgetReaderW */
#define SCARD_IOCTL_ADDREADERTOGROUPA RDP_SCARD_CTL_CODE(28) /* SCardAddReaderToGroupA */
#define SCARD_IOCTL_ADDREADERTOGROUPW RDP_SCARD_CTL_CODE(29) /* SCardAddReaderToGroupW */
#define SCARD_IOCTL_REMOVEREADERFROMGROUPA \
RDP_SCARD_CTL_CODE(30) /* SCardRemoveReaderFromGroupA \
*/
#define SCARD_IOCTL_REMOVEREADERFROMGROUPW \
RDP_SCARD_CTL_CODE(31) /* SCardRemoveReaderFromGroupW \
*/
#define SCARD_IOCTL_LOCATECARDSA RDP_SCARD_CTL_CODE(38) /* SCardLocateCardsA */
#define SCARD_IOCTL_LOCATECARDSW RDP_SCARD_CTL_CODE(39) /* SCardLocateCardsW */
#define SCARD_IOCTL_GETSTATUSCHANGEA RDP_SCARD_CTL_CODE(40) /* SCardGetStatusChangeA */
#define SCARD_IOCTL_GETSTATUSCHANGEW RDP_SCARD_CTL_CODE(41) /* SCardGetStatusChangeW */
#define SCARD_IOCTL_CANCEL RDP_SCARD_CTL_CODE(42) /* SCardCancel */
#define SCARD_IOCTL_CONNECTA RDP_SCARD_CTL_CODE(43) /* SCardConnectA */
#define SCARD_IOCTL_CONNECTW RDP_SCARD_CTL_CODE(44) /* SCardConnectW */
#define SCARD_IOCTL_RECONNECT RDP_SCARD_CTL_CODE(45) /* SCardReconnect */
#define SCARD_IOCTL_DISCONNECT RDP_SCARD_CTL_CODE(46) /* SCardDisconnect */
#define SCARD_IOCTL_BEGINTRANSACTION RDP_SCARD_CTL_CODE(47) /* SCardBeginTransaction */
#define SCARD_IOCTL_ENDTRANSACTION RDP_SCARD_CTL_CODE(48) /* SCardEndTransaction */
#define SCARD_IOCTL_STATE RDP_SCARD_CTL_CODE(49) /* SCardState */
#define SCARD_IOCTL_STATUSA RDP_SCARD_CTL_CODE(50) /* SCardStatusA */
#define SCARD_IOCTL_STATUSW RDP_SCARD_CTL_CODE(51) /* SCardStatusW */
#define SCARD_IOCTL_TRANSMIT RDP_SCARD_CTL_CODE(52) /* SCardTransmit */
#define SCARD_IOCTL_CONTROL RDP_SCARD_CTL_CODE(53) /* SCardControl */
#define SCARD_IOCTL_GETATTRIB RDP_SCARD_CTL_CODE(54) /* SCardGetAttrib */
#define SCARD_IOCTL_SETATTRIB RDP_SCARD_CTL_CODE(55) /* SCardSetAttrib */
#define SCARD_IOCTL_ACCESSSTARTEDEVENT RDP_SCARD_CTL_CODE(56) /* SCardAccessStartedEvent */
#define SCARD_IOCTL_RELEASETARTEDEVENT RDP_SCARD_CTL_CODE(57) /* SCardReleaseStartedEvent */
#define SCARD_IOCTL_LOCATECARDSBYATRA RDP_SCARD_CTL_CODE(58) /* SCardLocateCardsByATRA */
#define SCARD_IOCTL_LOCATECARDSBYATRW RDP_SCARD_CTL_CODE(59) /* SCardLocateCardsByATRW */
#define SCARD_IOCTL_READCACHEA RDP_SCARD_CTL_CODE(60) /* SCardReadCacheA */
#define SCARD_IOCTL_READCACHEW RDP_SCARD_CTL_CODE(61) /* SCardReadCacheW */
#define SCARD_IOCTL_WRITECACHEA RDP_SCARD_CTL_CODE(62) /* SCardWriteCacheA */
#define SCARD_IOCTL_WRITECACHEW RDP_SCARD_CTL_CODE(63) /* SCardWriteCacheW */
#define SCARD_IOCTL_GETTRANSMITCOUNT RDP_SCARD_CTL_CODE(64) /* SCardGetTransmitCount */
#define SCARD_IOCTL_GETREADERICON RDP_SCARD_CTL_CODE(65) /* SCardGetReaderIconA */
#define SCARD_IOCTL_GETDEVICETYPEID RDP_SCARD_CTL_CODE(66) /* SCardGetDeviceTypeIdA */
typedef struct _SMARTCARD_DEVICE SMARTCARD_DEVICE;
struct _SMARTCARD_OPERATION
{
IRP* irp;
void* call;
UINT32 ioControlCode;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
};
typedef struct _SMARTCARD_OPERATION SMARTCARD_OPERATION;
struct _SMARTCARD_CONTEXT
{
HANDLE thread;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,546 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Smartcard Device Service Virtual Channel
*
* Copyright 2011 O.S. Systems Software Ltda.
* Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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_SMARTCARD_OPERATIONS_MAIN_H
#define FREERDP_CHANNEL_SMARTCARD_OPERATIONS_MAIN_H
#include <winpr/crt.h>
#define RDP_SCARD_CTL_CODE(code) \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, (code), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define SCARD_IOCTL_ESTABLISHCONTEXT RDP_SCARD_CTL_CODE(5) /* SCardEstablishContext */
#define SCARD_IOCTL_RELEASECONTEXT RDP_SCARD_CTL_CODE(6) /* SCardReleaseContext */
#define SCARD_IOCTL_ISVALIDCONTEXT RDP_SCARD_CTL_CODE(7) /* SCardIsValidContext */
#define SCARD_IOCTL_LISTREADERGROUPSA RDP_SCARD_CTL_CODE(8) /* SCardListReaderGroupsA */
#define SCARD_IOCTL_LISTREADERGROUPSW RDP_SCARD_CTL_CODE(9) /* SCardListReaderGroupsW */
#define SCARD_IOCTL_LISTREADERSA RDP_SCARD_CTL_CODE(10) /* SCardListReadersA */
#define SCARD_IOCTL_LISTREADERSW RDP_SCARD_CTL_CODE(11) /* SCardListReadersW */
#define SCARD_IOCTL_INTRODUCEREADERGROUPA RDP_SCARD_CTL_CODE(20) /* SCardIntroduceReaderGroupA */
#define SCARD_IOCTL_INTRODUCEREADERGROUPW RDP_SCARD_CTL_CODE(21) /* SCardIntroduceReaderGroupW */
#define SCARD_IOCTL_FORGETREADERGROUPA RDP_SCARD_CTL_CODE(22) /* SCardForgetReaderGroupA */
#define SCARD_IOCTL_FORGETREADERGROUPW RDP_SCARD_CTL_CODE(23) /* SCardForgetReaderGroupW */
#define SCARD_IOCTL_INTRODUCEREADERA RDP_SCARD_CTL_CODE(24) /* SCardIntroduceReaderA */
#define SCARD_IOCTL_INTRODUCEREADERW RDP_SCARD_CTL_CODE(25) /* SCardIntroduceReaderW */
#define SCARD_IOCTL_FORGETREADERA RDP_SCARD_CTL_CODE(26) /* SCardForgetReaderA */
#define SCARD_IOCTL_FORGETREADERW RDP_SCARD_CTL_CODE(27) /* SCardForgetReaderW */
#define SCARD_IOCTL_ADDREADERTOGROUPA RDP_SCARD_CTL_CODE(28) /* SCardAddReaderToGroupA */
#define SCARD_IOCTL_ADDREADERTOGROUPW RDP_SCARD_CTL_CODE(29) /* SCardAddReaderToGroupW */
#define SCARD_IOCTL_REMOVEREADERFROMGROUPA \
RDP_SCARD_CTL_CODE(30) /* SCardRemoveReaderFromGroupA \
*/
#define SCARD_IOCTL_REMOVEREADERFROMGROUPW \
RDP_SCARD_CTL_CODE(31) /* SCardRemoveReaderFromGroupW \
*/
#define SCARD_IOCTL_LOCATECARDSA RDP_SCARD_CTL_CODE(38) /* SCardLocateCardsA */
#define SCARD_IOCTL_LOCATECARDSW RDP_SCARD_CTL_CODE(39) /* SCardLocateCardsW */
#define SCARD_IOCTL_GETSTATUSCHANGEA RDP_SCARD_CTL_CODE(40) /* SCardGetStatusChangeA */
#define SCARD_IOCTL_GETSTATUSCHANGEW RDP_SCARD_CTL_CODE(41) /* SCardGetStatusChangeW */
#define SCARD_IOCTL_CANCEL RDP_SCARD_CTL_CODE(42) /* SCardCancel */
#define SCARD_IOCTL_CONNECTA RDP_SCARD_CTL_CODE(43) /* SCardConnectA */
#define SCARD_IOCTL_CONNECTW RDP_SCARD_CTL_CODE(44) /* SCardConnectW */
#define SCARD_IOCTL_RECONNECT RDP_SCARD_CTL_CODE(45) /* SCardReconnect */
#define SCARD_IOCTL_DISCONNECT RDP_SCARD_CTL_CODE(46) /* SCardDisconnect */
#define SCARD_IOCTL_BEGINTRANSACTION RDP_SCARD_CTL_CODE(47) /* SCardBeginTransaction */
#define SCARD_IOCTL_ENDTRANSACTION RDP_SCARD_CTL_CODE(48) /* SCardEndTransaction */
#define SCARD_IOCTL_STATE RDP_SCARD_CTL_CODE(49) /* SCardState */
#define SCARD_IOCTL_STATUSA RDP_SCARD_CTL_CODE(50) /* SCardStatusA */
#define SCARD_IOCTL_STATUSW RDP_SCARD_CTL_CODE(51) /* SCardStatusW */
#define SCARD_IOCTL_TRANSMIT RDP_SCARD_CTL_CODE(52) /* SCardTransmit */
#define SCARD_IOCTL_CONTROL RDP_SCARD_CTL_CODE(53) /* SCardControl */
#define SCARD_IOCTL_GETATTRIB RDP_SCARD_CTL_CODE(54) /* SCardGetAttrib */
#define SCARD_IOCTL_SETATTRIB RDP_SCARD_CTL_CODE(55) /* SCardSetAttrib */
#define SCARD_IOCTL_ACCESSSTARTEDEVENT RDP_SCARD_CTL_CODE(56) /* SCardAccessStartedEvent */
#define SCARD_IOCTL_RELEASETARTEDEVENT RDP_SCARD_CTL_CODE(57) /* SCardReleaseStartedEvent */
#define SCARD_IOCTL_LOCATECARDSBYATRA RDP_SCARD_CTL_CODE(58) /* SCardLocateCardsByATRA */
#define SCARD_IOCTL_LOCATECARDSBYATRW RDP_SCARD_CTL_CODE(59) /* SCardLocateCardsByATRW */
#define SCARD_IOCTL_READCACHEA RDP_SCARD_CTL_CODE(60) /* SCardReadCacheA */
#define SCARD_IOCTL_READCACHEW RDP_SCARD_CTL_CODE(61) /* SCardReadCacheW */
#define SCARD_IOCTL_WRITECACHEA RDP_SCARD_CTL_CODE(62) /* SCardWriteCacheA */
#define SCARD_IOCTL_WRITECACHEW RDP_SCARD_CTL_CODE(63) /* SCardWriteCacheW */
#define SCARD_IOCTL_GETTRANSMITCOUNT RDP_SCARD_CTL_CODE(64) /* SCardGetTransmitCount */
#define SCARD_IOCTL_GETREADERICON RDP_SCARD_CTL_CODE(65) /* SCardGetReaderIconA */
#define SCARD_IOCTL_GETDEVICETYPEID RDP_SCARD_CTL_CODE(66) /* SCardGetDeviceTypeIdA */
#pragma pack(push, 1)
/* interface type_scard_pack */
/* [unique][version][uuid] */
typedef struct _REDIR_SCARDCONTEXT
{
/* [range] */ DWORD cbContext;
/* [size_is][unique] */ BYTE pbContext[8];
} REDIR_SCARDCONTEXT;
typedef struct _REDIR_SCARDHANDLE
{
/* [range] */ DWORD cbHandle;
/* [size_is] */ BYTE pbHandle[8];
} REDIR_SCARDHANDLE;
typedef struct _Long_Return
{
LONG ReturnCode;
} Long_Return;
typedef struct _longAndMultiString_Return
{
LONG ReturnCode;
/* [range] */ DWORD cBytes;
/* [size_is][unique] */ BYTE* msz;
} ListReaderGroups_Return;
typedef struct _longAndMultiString_Return ListReaders_Return;
typedef struct _EstablishContext_Return
{
LONG ReturnCode;
REDIR_SCARDCONTEXT hContext;
} EstablishContext_Return;
typedef struct _ReaderState_Return
{
DWORD dwCurrentState;
DWORD dwEventState;
/* [range] */ DWORD cbAtr;
BYTE rgbAtr[36];
} ReaderState_Return;
typedef struct _LocateCards_ATRMask
{
/* [range] */ DWORD cbAtr;
BYTE rgbAtr[36];
BYTE rgbMask[36];
} LocateCards_ATRMask;
typedef struct _GetStatusChange_Return
{
LONG ReturnCode;
/* [range] */ DWORD cReaders;
/* [size_is] */ ReaderState_Return* rgReaderStates;
} LocateCards_Return;
typedef struct _GetStatusChange_Return GetStatusChange_Return;
typedef struct _GetReaderIcon_Return
{
LONG ReturnCode;
ULONG cbDataLen;
BYTE* pbData;
} GetReaderIcon_Return;
typedef struct _GetDeviceTypeId_Return
{
LONG ReturnCode;
ULONG dwDeviceId;
} GetDeviceTypeId_Return;
typedef struct _Connect_Return
{
LONG ReturnCode;
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
DWORD dwActiveProtocol;
} Connect_Return;
typedef struct Reconnect_Return
{
LONG ReturnCode;
DWORD dwActiveProtocol;
} Reconnect_Return;
typedef struct _State_Return
{
LONG ReturnCode;
DWORD dwState;
DWORD dwProtocol;
/* [range] */ DWORD cbAtrLen;
/* [size_is][unique] */ BYTE rgAtr[36];
} State_Return;
typedef struct _Status_Return
{
LONG ReturnCode;
/* [range] */ DWORD cBytes;
/* [size_is][unique] */ BYTE* mszReaderNames;
DWORD dwState;
DWORD dwProtocol;
BYTE pbAtr[32];
/* [range] */ DWORD cbAtrLen;
} Status_Return;
typedef struct _SCardIO_Request
{
DWORD dwProtocol;
/* [range] */ DWORD cbExtraBytes;
/* [size_is][unique] */ BYTE* pbExtraBytes;
} SCardIO_Request;
typedef struct _Transmit_Return
{
LONG ReturnCode;
/* [unique] */ LPSCARD_IO_REQUEST pioRecvPci;
/* [range] */ DWORD cbRecvLength;
/* [size_is][unique] */ BYTE* pbRecvBuffer;
} Transmit_Return;
typedef struct _GetTransmitCount_Return
{
LONG ReturnCode;
DWORD cTransmitCount;
} GetTransmitCount_Return;
typedef struct _Control_Return
{
LONG ReturnCode;
/* [range] */ DWORD cbOutBufferSize;
/* [size_is][unique] */ BYTE* pvOutBuffer;
} Control_Return;
typedef struct _GetAttrib_Return
{
LONG ReturnCode;
/* [range] */ DWORD cbAttrLen;
/* [size_is][unique] */ BYTE* pbAttr;
} GetAttrib_Return;
typedef struct _ReadCache_Return
{
LONG ReturnCode;
/* [range] */ DWORD cbDataLen;
/* [size_is][unique] */ BYTE* pbData;
} ReadCache_Return;
#pragma pack(pop)
typedef struct _Handles_Call
{
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
} Handles_Call;
typedef struct _ListReaderGroups_Call
{
Handles_Call handles;
LONG fmszGroupsIsNULL;
DWORD cchGroups;
} ListReaderGroups_Call;
typedef struct _ListReaders_Call
{
Handles_Call handles;
/* [range] */ DWORD cBytes;
/* [size_is][unique] */ BYTE* mszGroups;
LONG fmszReadersIsNULL;
DWORD cchReaders;
} ListReaders_Call;
typedef struct _GetStatusChangeA_Call
{
Handles_Call handles;
DWORD dwTimeOut;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEA rgReaderStates;
} GetStatusChangeA_Call;
typedef struct _LocateCardsA_Call
{
Handles_Call handles;
/* [range] */ DWORD cBytes;
/* [size_is] */ CHAR* mszCards;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEA rgReaderStates;
} LocateCardsA_Call;
typedef struct _LocateCardsW_Call
{
Handles_Call handles;
/* [range] */ DWORD cBytes;
/* [size_is] */ WCHAR* mszCards;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEW rgReaderStates;
} LocateCardsW_Call;
typedef struct _LocateCardsByATRA_Call
{
Handles_Call handles;
/* [range] */ DWORD cAtrs;
/* [size_is] */ LocateCards_ATRMask* rgAtrMasks;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEA rgReaderStates;
} LocateCardsByATRA_Call;
typedef struct _LocateCardsByATRW_Call
{
Handles_Call handles;
/* [range] */ DWORD cAtrs;
/* [size_is] */ LocateCards_ATRMask* rgAtrMasks;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEW rgReaderStates;
} LocateCardsByATRW_Call;
typedef struct _GetStatusChangeW_Call
{
Handles_Call handles;
DWORD dwTimeOut;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEW rgReaderStates;
} GetStatusChangeW_Call;
typedef struct _GetReaderIcon_Call
{
Handles_Call handles;
WCHAR* szReaderName;
} GetReaderIcon_Call;
typedef struct _GetDeviceTypeId_Call
{
Handles_Call handles;
WCHAR* szReaderName;
} GetDeviceTypeId_Call;
typedef struct _Connect_Common_Call
{
Handles_Call handles;
DWORD dwShareMode;
DWORD dwPreferredProtocols;
} Connect_Common_Call;
typedef struct _ConnectA_Call
{
Connect_Common_Call Common;
/* [string] */ CHAR* szReader;
} ConnectA_Call;
typedef struct _ConnectW_Call
{
Connect_Common_Call Common;
/* [string] */ WCHAR* szReader;
} ConnectW_Call;
typedef struct _Reconnect_Call
{
Handles_Call handles;
DWORD dwShareMode;
DWORD dwPreferredProtocols;
DWORD dwInitialization;
} Reconnect_Call;
typedef struct _HCardAndDisposition_Call
{
Handles_Call handles;
DWORD dwDisposition;
} HCardAndDisposition_Call;
typedef struct _State_Call
{
Handles_Call handles;
LONG fpbAtrIsNULL;
DWORD cbAtrLen;
} State_Call;
typedef struct _Status_Call
{
Handles_Call handles;
LONG fmszReaderNamesIsNULL;
DWORD cchReaderLen;
DWORD cbAtrLen;
} Status_Call;
typedef struct _Transmit_Call
{
Handles_Call handles;
LPSCARD_IO_REQUEST pioSendPci;
/* [range] */ DWORD cbSendLength;
/* [size_is] */ BYTE* pbSendBuffer;
/* [unique] */ LPSCARD_IO_REQUEST pioRecvPci;
LONG fpbRecvBufferIsNULL;
DWORD cbRecvLength;
} Transmit_Call;
typedef struct _Long_Call
{
Handles_Call handles;
LONG LongValue;
} Long_Call;
typedef struct _Context_Call
{
Handles_Call handles;
} Context_Call;
typedef struct _ContextAndStringA_Call
{
Handles_Call handles;
/* [string] */ char* sz;
} ContextAndStringA_Call;
typedef struct _ContextAndStringW_Call
{
Handles_Call handles;
/* [string] */ WCHAR* sz;
} ContextAndStringW_Call;
typedef struct _ContextAndTwoStringA_Call
{
Handles_Call handles;
/* [string] */ char* sz1;
/* [string] */ char* sz2;
} ContextAndTwoStringA_Call;
typedef struct _ContextAndTwoStringW_Call
{
Handles_Call handles;
/* [string] */ WCHAR* sz1;
/* [string] */ WCHAR* sz2;
} ContextAndTwoStringW_Call;
typedef struct _EstablishContext_Call
{
Handles_Call handles;
DWORD dwScope;
} EstablishContext_Call;
typedef struct _GetTranmitCount_Call
{
Handles_Call handles;
} GetTransmitCount_Call;
typedef struct _Control_Call
{
Handles_Call handles;
DWORD dwControlCode;
/* [range] */ DWORD cbInBufferSize;
/* [size_is][unique] */ BYTE* pvInBuffer;
LONG fpvOutBufferIsNULL;
DWORD cbOutBufferSize;
} Control_Call;
typedef struct _GetAttrib_Call
{
Handles_Call handles;
DWORD dwAttrId;
LONG fpbAttrIsNULL;
DWORD cbAttrLen;
} GetAttrib_Call;
typedef struct _SetAttrib_Call
{
Handles_Call handles;
DWORD dwAttrId;
/* [range] */ DWORD cbAttrLen;
/* [size_is] */ BYTE* pbAttr;
} SetAttrib_Call;
typedef struct _ReadCache_Common
{
Handles_Call handles;
UUID* CardIdentifier;
DWORD FreshnessCounter;
LONG fPbDataIsNULL;
DWORD cbDataLen;
} ReadCache_Common;
typedef struct _ReadCacheA_Call
{
ReadCache_Common Common;
/* [string] */ char* szLookupName;
} ReadCacheA_Call;
typedef struct _ReadCacheW_Call
{
ReadCache_Common Common;
/* [string] */ WCHAR* szLookupName;
} ReadCacheW_Call;
typedef struct _WriteCache_Common
{
Handles_Call handles;
UUID* CardIdentifier;
DWORD FreshnessCounter;
/* [range] */ DWORD cbDataLen;
/* [size_is][unique] */ BYTE* pbData;
} WriteCache_Common;
typedef struct _WriteCacheA_Call
{
WriteCache_Common Common;
/* [string] */ char* szLookupName;
} WriteCacheA_Call;
typedef struct _WriteCacheW_Call
{
WriteCache_Common Common;
/* [string] */ WCHAR* szLookupName;
} WriteCacheW_Call;
struct _SMARTCARD_OPERATION
{
IRP* irp;
union
{
Handles_Call handles;
Long_Call lng;
Context_Call context;
ContextAndStringA_Call contextAndStringA;
ContextAndStringW_Call contextAndStringW;
ContextAndTwoStringA_Call contextAndTwoStringA;
ContextAndTwoStringW_Call contextAndTwoStringW;
EstablishContext_Call establishContext;
ListReaderGroups_Call listReaderGroups;
ListReaders_Call listReaders;
GetStatusChangeA_Call getStatusChangeA;
LocateCardsA_Call locateCardsA;
LocateCardsW_Call locateCardsW;
LocateCards_ATRMask locateCardsATRMask;
LocateCardsByATRA_Call locateCardsByATRA;
LocateCardsByATRW_Call locateCardsByATRW;
GetStatusChangeW_Call getStatusChangeW;
GetReaderIcon_Call getReaderIcon;
GetDeviceTypeId_Call getDeviceTypeId;
Connect_Common_Call connect;
ConnectA_Call connectA;
ConnectW_Call connectW;
Reconnect_Call reconnect;
HCardAndDisposition_Call hCardAndDisposition;
State_Call state;
Status_Call status;
SCardIO_Request scardIO;
Transmit_Call transmit;
GetTransmitCount_Call getTransmitCount;
Control_Call control;
GetAttrib_Call getAttrib;
SetAttrib_Call setAttrib;
ReadCache_Common readCache;
ReadCacheA_Call readCacheA;
ReadCacheW_Call readCacheW;
WriteCache_Common writeCache;
WriteCacheA_Call writeCacheA;
WriteCacheW_Call writeCacheW;
} call;
UINT32 ioControlCode;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
};
typedef struct _SMARTCARD_OPERATION SMARTCARD_OPERATION;
#endif /* FREERDP_CHANNEL_SMARTCARD_CLIENT_OPERATIONS_H */

File diff suppressed because it is too large Load Diff

View File

@ -28,420 +28,6 @@
#include <winpr/stream.h>
#include <winpr/smartcard.h>
#pragma pack(push, 1)
/* interface type_scard_pack */
/* [unique][version][uuid] */
typedef struct _REDIR_SCARDCONTEXT
{
/* [range] */ DWORD cbContext;
/* [size_is][unique] */ BYTE pbContext[8];
} REDIR_SCARDCONTEXT;
typedef struct _REDIR_SCARDHANDLE
{
/* [range] */ DWORD cbHandle;
/* [size_is] */ BYTE pbHandle[8];
} REDIR_SCARDHANDLE;
typedef struct _Long_Call
{
LONG LongValue;
} Long_Call;
typedef struct _Long_Return
{
LONG ReturnCode;
} Long_Return;
typedef struct _longAndMultiString_Return
{
LONG ReturnCode;
/* [range] */ DWORD cBytes;
/* [size_is][unique] */ BYTE* msz;
} ListReaderGroups_Return;
typedef struct _longAndMultiString_Return ListReaders_Return;
typedef struct _Context_Call
{
REDIR_SCARDCONTEXT hContext;
} Context_Call;
typedef struct _ContextAndStringA_Call
{
REDIR_SCARDCONTEXT hContext;
/* [string] */ char* sz;
} ContextAndStringA_Call;
typedef struct _ContextAndStringW_Call
{
REDIR_SCARDCONTEXT hContext;
/* [string] */ WCHAR* sz;
} ContextAndStringW_Call;
typedef struct _ContextAndTwoStringA_Call
{
REDIR_SCARDCONTEXT hContext;
/* [string] */ char* sz1;
/* [string] */ char* sz2;
} ContextAndTwoStringA_Call;
typedef struct _ContextAndTwoStringW_Call
{
REDIR_SCARDCONTEXT hContext;
/* [string] */ WCHAR* sz1;
/* [string] */ WCHAR* sz2;
} ContextAndTwoStringW_Call;
typedef struct _EstablishContext_Call
{
DWORD dwScope;
} EstablishContext_Call;
typedef struct _EstablishContext_Return
{
LONG ReturnCode;
REDIR_SCARDCONTEXT hContext;
} EstablishContext_Return;
typedef struct _ListReaderGroups_Call
{
REDIR_SCARDCONTEXT hContext;
LONG fmszGroupsIsNULL;
DWORD cchGroups;
} ListReaderGroups_Call;
typedef struct _ListReaders_Call
{
REDIR_SCARDCONTEXT hContext;
/* [range] */ DWORD cBytes;
/* [size_is][unique] */ BYTE* mszGroups;
LONG fmszReadersIsNULL;
DWORD cchReaders;
} ListReaders_Call;
typedef struct _ReaderState_Return
{
DWORD dwCurrentState;
DWORD dwEventState;
/* [range] */ DWORD cbAtr;
BYTE rgbAtr[36];
} ReaderState_Return;
typedef struct _GetStatusChangeA_Call
{
REDIR_SCARDCONTEXT hContext;
DWORD dwTimeOut;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEA rgReaderStates;
} GetStatusChangeA_Call;
typedef struct _LocateCardsA_Call
{
REDIR_SCARDCONTEXT hContext;
/* [range] */ DWORD cBytes;
/* [size_is] */ CHAR* mszCards;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEA rgReaderStates;
} LocateCardsA_Call;
typedef struct _LocateCardsW_Call
{
REDIR_SCARDCONTEXT hContext;
/* [range] */ DWORD cBytes;
/* [size_is] */ WCHAR* mszCards;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEW rgReaderStates;
} LocateCardsW_Call;
typedef struct _LocateCards_ATRMask
{
/* [range] */ DWORD cbAtr;
BYTE rgbAtr[36];
BYTE rgbMask[36];
} LocateCards_ATRMask;
typedef struct _LocateCardsByATRA_Call
{
REDIR_SCARDCONTEXT hContext;
/* [range] */ DWORD cAtrs;
/* [size_is] */ LocateCards_ATRMask* rgAtrMasks;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEA rgReaderStates;
} LocateCardsByATRA_Call;
typedef struct _LocateCardsByATRW_Call
{
REDIR_SCARDCONTEXT hContext;
/* [range] */ DWORD cAtrs;
/* [size_is] */ LocateCards_ATRMask* rgAtrMasks;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEW rgReaderStates;
} LocateCardsByATRW_Call;
typedef struct _GetStatusChange_Return
{
LONG ReturnCode;
/* [range] */ DWORD cReaders;
/* [size_is] */ ReaderState_Return* rgReaderStates;
} LocateCards_Return;
typedef struct _GetStatusChange_Return GetStatusChange_Return;
typedef struct _GetStatusChangeW_Call
{
REDIR_SCARDCONTEXT hContext;
DWORD dwTimeOut;
/* [range] */ DWORD cReaders;
/* [size_is] */ LPSCARD_READERSTATEW rgReaderStates;
} GetStatusChangeW_Call;
typedef struct _GetReaderIcon_Call
{
REDIR_SCARDCONTEXT hContext;
WCHAR* szReaderName;
} GetReaderIcon_Call;
typedef struct _GetReaderIcon_Return
{
LONG ReturnCode;
ULONG cbDataLen;
BYTE* pbData;
} GetReaderIcon_Return;
typedef struct _GetDeviceTypeId_Call
{
REDIR_SCARDCONTEXT hContext;
WCHAR* szReaderName;
} GetDeviceTypeId_Call;
typedef struct _GetDeviceTypeId_Return
{
LONG ReturnCode;
ULONG dwDeviceId;
} GetDeviceTypeId_Return;
typedef struct _Connect_Common
{
REDIR_SCARDCONTEXT hContext;
DWORD dwShareMode;
DWORD dwPreferredProtocols;
} Connect_Common;
typedef struct _ConnectA_Call
{
/* [string] */ CHAR* szReader;
Connect_Common Common;
} ConnectA_Call;
typedef struct _ConnectW_Call
{
/* [string] */ WCHAR* szReader;
Connect_Common Common;
} ConnectW_Call;
typedef struct _Connect_Return
{
LONG ReturnCode;
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
DWORD dwActiveProtocol;
} Connect_Return;
typedef struct _Reconnect_Call
{
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
DWORD dwShareMode;
DWORD dwPreferredProtocols;
DWORD dwInitialization;
} Reconnect_Call;
typedef struct Reconnect_Return
{
LONG ReturnCode;
DWORD dwActiveProtocol;
} Reconnect_Return;
typedef struct _HCardAndDisposition_Call
{
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
DWORD dwDisposition;
} HCardAndDisposition_Call;
typedef struct _State_Call
{
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
LONG fpbAtrIsNULL;
DWORD cbAtrLen;
} State_Call;
typedef struct _State_Return
{
LONG ReturnCode;
DWORD dwState;
DWORD dwProtocol;
/* [range] */ DWORD cbAtrLen;
/* [size_is][unique] */ BYTE rgAtr[36];
} State_Return;
typedef struct _Status_Call
{
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
LONG fmszReaderNamesIsNULL;
DWORD cchReaderLen;
DWORD cbAtrLen;
} Status_Call;
typedef struct _Status_Return
{
LONG ReturnCode;
/* [range] */ DWORD cBytes;
/* [size_is][unique] */ BYTE* mszReaderNames;
DWORD dwState;
DWORD dwProtocol;
BYTE pbAtr[32];
/* [range] */ DWORD cbAtrLen;
} Status_Return;
typedef struct _SCardIO_Request
{
DWORD dwProtocol;
/* [range] */ DWORD cbExtraBytes;
/* [size_is][unique] */ BYTE* pbExtraBytes;
} SCardIO_Request;
typedef struct _Transmit_Call
{
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
LPSCARD_IO_REQUEST pioSendPci;
/* [range] */ DWORD cbSendLength;
/* [size_is] */ BYTE* pbSendBuffer;
/* [unique] */ LPSCARD_IO_REQUEST pioRecvPci;
LONG fpbRecvBufferIsNULL;
DWORD cbRecvLength;
} Transmit_Call;
typedef struct _Transmit_Return
{
LONG ReturnCode;
/* [unique] */ LPSCARD_IO_REQUEST pioRecvPci;
/* [range] */ DWORD cbRecvLength;
/* [size_is][unique] */ BYTE* pbRecvBuffer;
} Transmit_Return;
typedef struct _GetTransmitCount_Call
{
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
} GetTransmitCount_Call;
typedef struct _GetTransmitCount_Return
{
LONG ReturnCode;
DWORD cTransmitCount;
} GetTransmitCount_Return;
typedef struct _Control_Call
{
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
DWORD dwControlCode;
/* [range] */ DWORD cbInBufferSize;
/* [size_is][unique] */ BYTE* pvInBuffer;
LONG fpvOutBufferIsNULL;
DWORD cbOutBufferSize;
} Control_Call;
typedef struct _Control_Return
{
LONG ReturnCode;
/* [range] */ DWORD cbOutBufferSize;
/* [size_is][unique] */ BYTE* pvOutBuffer;
} Control_Return;
typedef struct _GetAttrib_Call
{
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
DWORD dwAttrId;
LONG fpbAttrIsNULL;
DWORD cbAttrLen;
} GetAttrib_Call;
typedef struct _GetAttrib_Return
{
LONG ReturnCode;
/* [range] */ DWORD cbAttrLen;
/* [size_is][unique] */ BYTE* pbAttr;
} GetAttrib_Return;
typedef struct _SetAttrib_Call
{
REDIR_SCARDCONTEXT hContext;
REDIR_SCARDHANDLE hCard;
DWORD dwAttrId;
/* [range] */ DWORD cbAttrLen;
/* [size_is] */ BYTE* pbAttr;
} SetAttrib_Call;
typedef struct _ReadCache_Common
{
REDIR_SCARDCONTEXT hContext;
UUID* CardIdentifier;
DWORD FreshnessCounter;
LONG fPbDataIsNULL;
DWORD cbDataLen;
} ReadCache_Common;
typedef struct _ReadCacheA_Call
{
/* [string] */ char* szLookupName;
ReadCache_Common Common;
} ReadCacheA_Call;
typedef struct _ReadCacheW_Call
{
/* [string] */ WCHAR* szLookupName;
ReadCache_Common Common;
} ReadCacheW_Call;
typedef struct _ReadCache_Return
{
LONG ReturnCode;
/* [range] */ DWORD cbDataLen;
/* [size_is][unique] */ BYTE* pbData;
} ReadCache_Return;
typedef struct _WriteCache_Common
{
REDIR_SCARDCONTEXT hContext;
UUID* CardIdentifier;
DWORD FreshnessCounter;
/* [range] */ DWORD cbDataLen;
/* [size_is][unique] */ BYTE* pbData;
} WriteCache_Common;
typedef struct _WriteCacheA_Call
{
/* [string] */ char* szLookupName;
WriteCache_Common Common;
} WriteCacheA_Call;
typedef struct _WriteCacheW_Call
{
/* [string] */ WCHAR* szLookupName;
WriteCache_Common Common;
} WriteCacheW_Call;
#pragma pack(pop)
#define SMARTCARD_COMMON_TYPE_HEADER_LENGTH 8
#define SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH 8
@ -554,7 +140,8 @@ LONG smartcard_unpack_get_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s,
GetAttrib_Call* call);
LONG smartcard_pack_get_attrib_return(SMARTCARD_DEVICE* smartcard, wStream* s,
const GetAttrib_Return* ret, DWORD dwAttrId);
const GetAttrib_Return* ret, DWORD dwAttrId,
DWORD cbAttrCallLen);
LONG smartcard_unpack_set_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s,
SetAttrib_Call* call);

View File

@ -242,7 +242,7 @@ static UINT urbdrc_process_io_control(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* c
Stream_Read_UINT32(s, OutputBufferSize);
Stream_Read_UINT32(s, RequestId);
InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize);
out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
if (!out)
return ERROR_OUTOFMEMORY;
@ -266,7 +266,11 @@ static UINT urbdrc_process_io_control(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* c
if (success)
{
Stream_Seek(out, OutputBufferSize);
if (!Stream_SafeSeek(out, OutputBufferSize))
{
Stream_Free(out, TRUE);
return ERROR_INVALID_DATA;
}
if (pdev->isExist(pdev) == 0)
Stream_Write_UINT32(out, 0);
@ -454,11 +458,13 @@ static UINT urb_select_configuration(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* ca
if (MsConfig)
MsOutSize = MsConfig->MsOutSize;
if (MsOutSize > SIZE_MAX - 36)
return ERROR_INVALID_DATA;
if (MsOutSize > 0)
{
if ((size_t)MsOutSize > SIZE_MAX - 36)
return ERROR_INVALID_DATA;
out_size = 36 + MsOutSize;
}
else
out_size = 44;
@ -763,9 +769,7 @@ static void urb_isoch_transfer_cb(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callb
Stream_Write_UINT32(out, OutputBufferSize); /** OutputBufferSize */
Stream_Seek(out, OutputBufferSize);
if (!pdev->isChannelClosed(pdev))
callback->channel->Write(callback->channel, Stream_GetPosition(out), Stream_Buffer(out),
NULL);
stream_write_and_free(callback->plugin, callback->channel, out);
}
}

View File

@ -75,12 +75,61 @@ struct _ASYNC_TRANSFER_USER_DATA
UINT32 OutputBufferSize;
URBDRC_CHANNEL_CALLBACK* callback;
t_isoch_transfer_cb cb;
wHashTable* queue;
wArrayList* queue;
#if !defined(HAVE_STREAM_ID_API)
UINT32 streamID;
#endif
};
static void request_free(void* value);
static struct libusb_transfer* list_contains(wArrayList* list, UINT32 streamID)
{
int x, count;
if (!list)
return NULL;
count = ArrayList_Count(list);
for (x = 0; x < count; x++)
{
struct libusb_transfer* transfer = ArrayList_GetItem(list, x);
#if defined(HAVE_STREAM_ID_API)
const UINT32 currentID = libusb_transfer_get_stream_id(transfer);
#else
const ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
const UINT32 currentID = user_data->streamID;
#endif
if (currentID == streamID)
return transfer;
}
return NULL;
}
static UINT32 stream_id_from_buffer(struct libusb_transfer* transfer)
{
if (!transfer)
return 0;
#if defined(HAVE_STREAM_ID_API)
return libusb_transfer_get_stream_id(transfer);
#else
ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
if (!user_data)
return 0;
return user_data->streamID;
#endif
}
static void set_stream_id_for_buffer(struct libusb_transfer* transfer, UINT32 streamID)
{
#if defined(HAVE_STREAM_ID_API)
libusb_transfer_set_stream_id(transfer, streamID);
#else
ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
if (!user_data)
return;
user_data->streamID = streamID;
#endif
}
static BOOL log_libusb_result(wLog* log, DWORD lvl, const char* fmt, int error, ...)
{
if (error < 0)
@ -176,7 +225,6 @@ static ASYNC_TRANSFER_USER_DATA* async_transfer_user_data_new(IUDEVICE* idev, UI
static void async_transfer_user_data_free(ASYNC_TRANSFER_USER_DATA* user_data)
{
if (user_data)
{
Stream_Free(user_data->data, TRUE);
@ -187,15 +235,12 @@ static void async_transfer_user_data_free(ASYNC_TRANSFER_USER_DATA* user_data)
static void func_iso_callback(struct libusb_transfer* transfer)
{
ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
#if defined(HAVE_STREAM_ID_API)
const UINT32 streamID = libusb_transfer_get_stream_id(transfer);
#else
const UINT32 streamID = user_data->streamID;
#endif
const UINT32 streamID = stream_id_from_buffer(transfer);
wArrayList* list = user_data->queue;
ArrayList_Lock(list);
switch (transfer->status)
{
case LIBUSB_TRANSFER_COMPLETED:
{
int i;
@ -235,7 +280,7 @@ static void func_iso_callback(struct libusb_transfer* transfer)
const UINT32 InterfaceId =
((STREAM_ID_PROXY << 30) | user_data->idev->get_ReqCompletion(user_data->idev));
if (HashTable_Contains(user_data->queue, (void*)(size_t)streamID))
if (list_contains(list, streamID))
{
if (!user_data->noack)
{
@ -247,13 +292,14 @@ static void func_iso_callback(struct libusb_transfer* transfer)
user_data->OutputBufferSize);
user_data->data = NULL;
}
HashTable_Remove(user_data->queue, (void*)(size_t)streamID);
ArrayList_Remove(list, transfer);
}
}
break;
default:
break;
}
ArrayList_Unlock(list);
}
static const LIBUSB_ENDPOINT_DESCEIPTOR* func_get_ep_desc(LIBUSB_CONFIG_DESCRIPTOR* LibusbConfig,
@ -289,6 +335,7 @@ static void func_bulk_transfer_cb(struct libusb_transfer* transfer)
{
ASYNC_TRANSFER_USER_DATA* user_data;
uint32_t streamID;
wArrayList* list;
user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
if (!user_data)
@ -296,14 +343,11 @@ static void func_bulk_transfer_cb(struct libusb_transfer* transfer)
WLog_ERR(TAG, "[%s]: Invalid transfer->user_data!");
return;
}
list = user_data->queue;
ArrayList_Lock(list);
streamID = stream_id_from_buffer(transfer);
#if defined(HAVE_STREAM_ID_API)
streamID = libusb_transfer_get_stream_id(transfer);
#else
streamID = user_data->streamID;
#endif
if (HashTable_Contains(user_data->queue, (void*)(size_t)streamID))
if (list_contains(list, streamID))
{
const UINT32 InterfaceId =
((STREAM_ID_PROXY << 30) | user_data->idev->get_ReqCompletion(user_data->idev));
@ -314,8 +358,9 @@ static void func_bulk_transfer_cb(struct libusb_transfer* transfer)
transfer->status, user_data->StartFrame, user_data->ErrorCount,
transfer->actual_length);
user_data->data = NULL;
HashTable_Remove(user_data->queue, (void*)(size_t)streamID);
ArrayList_Remove(list, transfer);
}
ArrayList_Unlock(list);
}
static BOOL func_set_usbd_status(URBDRC_PLUGIN* urbdrc, UDEVICE* pdev, UINT32* status,
@ -799,7 +844,7 @@ static UINT32 libusb_udev_control_query_device_text(IUDEVICE* idev, UINT32 TextT
if ((ret <= 0) || (ret <= 4) || (slen <= 4) || (locale != LIBUSB_DT_STRING) ||
(ret > UINT8_MAX))
{
char* msg = "SHORT_DESCRIPTOR";
const char* msg = "SHORT_DESCRIPTOR";
if (ret < 0)
msg = libusb_error_name(ret);
WLog_Print(urbdrc->log, WLOG_DEBUG,
@ -841,7 +886,8 @@ static UINT32 libusb_udev_control_query_device_text(IUDEVICE* idev, UINT32 TextT
sprintf_s(deviceLocation, sizeof(deviceLocation),
"Port_#%04" PRIu8 ".Hub_#%04" PRIu8 "", device_address, bus_number);
len = strnlen(deviceLocation, MIN(sizeof(deviceLocation), inSize - 1));
len = strnlen(deviceLocation,
MIN(sizeof(deviceLocation), (inSize > 0) ? inSize - 1U : 0));
for (i = 0; i < len; i++)
text[i] = (WCHAR)deviceLocation[i];
text[len++] = '\0';
@ -883,7 +929,10 @@ static int libusb_udev_os_feature_descriptor_request(IUDEVICE* idev, UINT32 Requ
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | Recipient,
bMS_Vendorcode, (InterfaceNumber << 8) | Ms_PageIndex,
Ms_featureDescIndex, Buffer, *BufferSize, Timeout);
*BufferSize = error;
log_libusb_result(pdev->urbdrc->log, WLOG_DEBUG, "libusb_control_transfer", error);
if (error >= 0)
*BufferSize = error;
}
if (error < 0)
@ -1043,10 +1092,28 @@ static int libusb_udev_is_already_send(IUDEVICE* idev)
return (pdev->status & URBDRC_DEVICE_ALREADY_SEND) ? 1 : 0;
}
/* This is called from channel cleanup code.
* Avoid double free, just remove the device and mark the channel closed. */
static void libusb_udev_mark_channel_closed(IUDEVICE* idev)
{
UDEVICE* pdev = (UDEVICE*)idev;
if (pdev && ((pdev->status & URBDRC_DEVICE_CHANNEL_CLOSED) == 0))
{
URBDRC_PLUGIN* urbdrc = pdev->urbdrc;
const uint8_t busNr = idev->get_bus_number(idev);
const uint8_t devNr = idev->get_dev_number(idev);
pdev->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
urbdrc->udevman->unregister_udevice(urbdrc->udevman, busNr, devNr);
}
}
/* This is called by local events where the device is removed or in an error
* state. Remove the device from redirection and close the channel. */
static void libusb_udev_channel_closed(IUDEVICE* idev)
{
UDEVICE* pdev = (UDEVICE*)idev;
if (pdev)
if (pdev && ((pdev->status & URBDRC_DEVICE_CHANNEL_CLOSED) == 0))
{
URBDRC_PLUGIN* urbdrc = pdev->urbdrc;
const uint8_t busNr = idev->get_bus_number(idev);
@ -1060,10 +1127,8 @@ static void libusb_udev_channel_closed(IUDEVICE* idev)
pdev->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
if (channel)
{
/* Notify the server the device is no longer available. */
channel->Write(channel, 0, NULL, NULL);
}
urbdrc->udevman->unregister_udevice(urbdrc->udevman, busNr, devNr);
}
}
@ -1159,19 +1224,21 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* c
return -1;
}
iso_transfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
/** process URB_FUNCTION_IOSCH_TRANSFER */
libusb_fill_iso_transfer(iso_transfer, pdev->libusb_handle, EndpointAddress,
Stream_Pointer(user_data->data), BufferSize, NumberOfPackets,
func_iso_callback, user_data, Timeout);
#if defined(HAVE_STREAM_ID_API)
libusb_transfer_set_stream_id(iso_transfer, streamID);
#else
user_data->streamID = streamID;
#endif
set_stream_id_for_buffer(iso_transfer, streamID);
libusb_set_iso_packet_lengths(iso_transfer, iso_packet_size);
HashTable_Add(pdev->request_queue, (void*)(size_t)streamID, iso_transfer);
if (ArrayList_Add(pdev->request_queue, iso_transfer) < 0)
{
WLog_Print(urbdrc->log, WLOG_WARN,
"Failed to queue iso transfer, streamID %08" PRIx32 " already in use!",
streamID);
request_free(iso_transfer);
return -1;
}
return libusb_submit_transfer(iso_transfer);
}
@ -1231,7 +1298,6 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, URBDRC_CHANNEL
async_transfer_user_data_free(user_data);
return -1;
}
transfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
ep_desc = func_get_ep_desc(pdev->LibusbConfig, pdev->MsConfig, EndpointAddress);
@ -1239,8 +1305,7 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, URBDRC_CHANNEL
{
WLog_Print(urbdrc->log, WLOG_ERROR, "func_get_ep_desc: endpoint 0x%" PRIx32 " not found",
EndpointAddress);
libusb_free_transfer(transfer);
async_transfer_user_data_free(user_data);
request_free(transfer);
return -1;
}
@ -1271,26 +1336,27 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, URBDRC_CHANNEL
"urb_bulk_or_interrupt_transfer:"
" other transfer type 0x%" PRIX32 "",
transfer_type);
async_transfer_user_data_free(user_data);
libusb_free_transfer(transfer);
request_free(transfer);
return -1;
}
#if defined(HAVE_STREAM_ID_API)
libusb_transfer_set_stream_id(transfer, streamID);
#else
user_data->streamID = streamID;
#endif
HashTable_Add(pdev->request_queue, (void*)(size_t)streamID, transfer);
set_stream_id_for_buffer(transfer, streamID);
if (ArrayList_Add(pdev->request_queue, transfer) < 0)
{
WLog_Print(urbdrc->log, WLOG_WARN,
"Failed to queue transfer, streamID %08" PRIx32 " already in use!", streamID);
request_free(transfer);
return -1;
}
return libusb_submit_transfer(transfer);
}
static int func_cancel_xact_request(URBDRC_PLUGIN* urbdrc, wHashTable* queue, uint32_t streamID,
struct libusb_transfer* transfer)
static int func_cancel_xact_request(URBDRC_PLUGIN* urbdrc, struct libusb_transfer* transfer)
{
int status;
if (!urbdrc || !queue || !transfer)
if (!urbdrc || !transfer)
return -1;
status = libusb_cancel_transfer(transfer);
@ -1305,50 +1371,51 @@ static int func_cancel_xact_request(URBDRC_PLUGIN* urbdrc, wHashTable* queue, ui
return 0;
}
static void libusb_udev_cancel_all_transfer_request(IUDEVICE* idev)
{
UDEVICE* pdev = (UDEVICE*)idev;
ULONG_PTR* keys;
int count, x;
if (!pdev || !pdev->request_queue || !pdev->urbdrc)
return;
count = HashTable_GetKeys(pdev->request_queue, &keys);
ArrayList_Lock(pdev->request_queue);
count = ArrayList_Count(pdev->request_queue);
for (x = 0; x < count; x++)
{
struct libusb_transfer* transfer =
HashTable_GetItemValue(pdev->request_queue, (void*)keys[x]);
func_cancel_xact_request(pdev->urbdrc, pdev->request_queue, (uint32_t)keys[x], transfer);
struct libusb_transfer* transfer = ArrayList_GetItem(pdev->request_queue, x);
func_cancel_xact_request(pdev->urbdrc, transfer);
}
free(keys);
ArrayList_Unlock(pdev->request_queue);
}
static int libusb_udev_cancel_transfer_request(IUDEVICE* idev, UINT32 RequestId)
{
int rc = -1;
UDEVICE* pdev = (UDEVICE*)idev;
struct libusb_transfer* transfer;
URBDRC_PLUGIN* urbdrc;
BOOL id1;
uint32_t cancelID;
uint32_t cancelID1 = 0x40000000 | RequestId;
uint32_t cancelID2 = 0x80000000 | RequestId;
if (!idev || !pdev->urbdrc || !pdev->request_queue)
return -1;
id1 = HashTable_Contains(pdev->request_queue, (void*)(size_t)cancelID1);
ArrayList_Lock(pdev->request_queue);
transfer = list_contains(pdev->request_queue, cancelID1);
if (!transfer)
transfer = list_contains(pdev->request_queue, cancelID2);
if (!id1)
return -1;
if (transfer)
{
URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)pdev->urbdrc;
urbdrc = (URBDRC_PLUGIN*)pdev->urbdrc;
cancelID = (id1) ? cancelID1 : cancelID2;
transfer = HashTable_GetItemValue(pdev->request_queue, (void*)(size_t)cancelID);
return func_cancel_xact_request(urbdrc, pdev->request_queue, cancelID, transfer);
rc = func_cancel_xact_request(urbdrc, transfer);
}
ArrayList_Unlock(pdev->request_queue);
return rc;
}
BASIC_STATE_FUNC_DEFINED(channelManager, IWTSVirtualChannelManager*)
@ -1394,6 +1461,7 @@ static void udev_free(IUDEVICE* idev)
urbdrc = udev->urbdrc;
libusb_udev_cancel_all_transfer_request(&udev->iface);
if (udev->libusb_handle)
{
rc = libusb_reset_device(udev->libusb_handle);
@ -1403,7 +1471,7 @@ static void udev_free(IUDEVICE* idev)
/* release all interface and attach kernel driver */
udev->iface.attach_kernel_driver(idev);
HashTable_Free(udev->request_queue);
ArrayList_Free(udev->request_queue);
/* free the config descriptor that send from windows */
msusb_msconfig_free(udev->MsConfig);
libusb_close(udev->libusb_handle);
@ -1433,6 +1501,7 @@ static void udev_load_interface(UDEVICE* pdev)
pdev->iface.isChannelClosed = libusb_udev_is_channel_closed;
pdev->iface.setAlreadySend = libusb_udev_set_already_send;
pdev->iface.setChannelClosed = libusb_udev_channel_closed;
pdev->iface.markChannelClosed = libusb_udev_mark_channel_closed;
pdev->iface.getPath = libusb_udev_get_path;
/* Transfer */
pdev->iface.isoch_transfer = libusb_udev_isoch_transfer;
@ -1540,6 +1609,8 @@ static void request_free(void* value)
user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
async_transfer_user_data_free(user_data);
transfer->user_data = NULL;
libusb_free_transfer(transfer);
}
static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, libusb_context* context, LIBUSB_DEVICE* device,
@ -1638,12 +1709,12 @@ static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, libusb_context* context, LIBUS
/* initialize pdev */
pdev->bus_number = bus_number;
pdev->dev_number = dev_number;
pdev->request_queue = HashTable_New(TRUE);
pdev->request_queue = ArrayList_New(TRUE);
if (!pdev->request_queue)
goto fail;
pdev->request_queue->valueFree = request_free;
ArrayList_Object(pdev->request_queue)->fnObjectFree = request_free;
/* set config of windows */
pdev->MsConfig = msusb_msconfig_new();
@ -1652,9 +1723,9 @@ static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, libusb_context* context, LIBUS
goto fail;
// deb_config_msg(pdev->libusb_dev, config_temp, devDescriptor->bNumConfigurations);
return (IUDEVICE*)pdev;
return &pdev->iface;
fail:
pdev->iface.free((IUDEVICE*)pdev);
pdev->iface.free(&pdev->iface);
return NULL;
}
@ -1673,12 +1744,11 @@ size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UINT16 idVendo
WLog_Print(urbdrc->log, WLOG_INFO, "VID: 0x%04" PRIX16 ", PID: 0x%04" PRIX16 "", idVendor,
idProduct);
array = (UDEVICE**)calloc(16, sizeof(UDEVICE*));
total_device = libusb_get_device_list(ctx, &libusb_list);
array = (UDEVICE**)calloc(total_device, sizeof(UDEVICE*));
if (!array)
return 0;
total_device = libusb_get_device_list(ctx, &libusb_list);
goto fail;
for (i = 0; i < total_device; i++)
{
@ -1697,6 +1767,7 @@ size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UINT16 idVendo
free(descriptor);
}
fail:
libusb_free_device_list(libusb_list, 1);
*devArray = (IUDEVICE**)array;
return num;

View File

@ -63,7 +63,7 @@ struct _UDEVICE
MSUSB_CONFIG_DESCRIPTOR* MsConfig;
LIBUSB_CONFIG_DESCRIPTOR* LibusbConfig;
wHashTable* request_queue;
wArrayList* request_queue;
URBDRC_PLUGIN* urbdrc;
};

View File

@ -399,6 +399,36 @@ static IUDEVICE* udevman_get_udevice_by_UsbDevice(IUDEVMAN* idevman, UINT32 UsbD
return NULL;
}
static IUDEVICE* udevman_get_udevice_by_ChannelID(IUDEVMAN* idevman, UINT32 channelID)
{
UDEVICE* pdev;
URBDRC_PLUGIN* urbdrc;
if (!idevman || !idevman->plugin)
return NULL;
/* Mask highest 2 bits, must be ignored */
urbdrc = (URBDRC_PLUGIN*)idevman->plugin;
idevman->loading_lock(idevman);
idevman->rewind(idevman);
while (idevman->has_next(idevman))
{
pdev = (UDEVICE*)idevman->get_next(idevman);
if (pdev->channelID == channelID)
{
idevman->loading_unlock(idevman);
return (IUDEVICE*)pdev;
}
}
idevman->loading_unlock(idevman);
WLog_Print(urbdrc->log, WLOG_WARN, "Failed to find a USB device mapped to channelID=%08" PRIx32,
channelID);
return NULL;
}
static void udevman_loading_lock(IUDEVMAN* idevman)
{
UDEVMAN* udevman = (UDEVMAN*)idevman;
@ -786,6 +816,7 @@ static void udevman_load_interface(UDEVMAN* udevman)
udevman->iface.register_udevice = udevman_register_udevice;
udevman->iface.unregister_udevice = udevman_unregister_udevice;
udevman->iface.get_udevice_by_UsbDevice = udevman_get_udevice_by_UsbDevice;
udevman->iface.get_udevice_by_ChannelID = udevman_get_udevice_by_ChannelID;
/* Extension */
udevman->iface.isAutoAdd = udevman_is_auto_add;
/* Basic state */

View File

@ -621,6 +621,12 @@ static UINT urbdrc_on_close(IWTSVirtualChannelCallback* pChannelCallback)
UINT32 control = callback->channel_mgr->GetChannelId(callback->channel);
if (udevman->controlChannelId == control)
udevman->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
else
{ /* Need to notify the local backend the device is gone */
IUDEVICE* pdev = udevman->get_udevice_by_ChannelID(udevman, control);
if (pdev)
pdev->markChannelClosed(pdev);
}
}
}
}
@ -673,6 +679,11 @@ static UINT urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana
if (!urbdrc || !urbdrc->udevman)
return ERROR_INVALID_PARAMETER;
if (urbdrc->initialized)
{
WLog_ERR(TAG, "[%s] channel initialized twice, aborting", URBDRC_CHANNEL_NAME);
return ERROR_INVALID_DATA;
}
udevman = urbdrc->udevman;
urbdrc->listener_callback =
(URBDRC_LISTENER_CALLBACK*)calloc(1, sizeof(URBDRC_LISTENER_CALLBACK));
@ -691,10 +702,12 @@ static UINT urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana
if (status != CHANNEL_RC_OK)
return status;
status = CHANNEL_RC_OK;
if (udevman->listener_created_callback)
return udevman->listener_created_callback(udevman);
status = udevman->listener_created_callback(udevman);
return CHANNEL_RC_OK;
urbdrc->initialized = status == CHANNEL_RC_OK;
return status;
}
/**

View File

@ -85,6 +85,7 @@ struct _URBDRC_PLUGIN
wLog* log;
IWTSListener* listener;
BOOL initialized;
};
typedef BOOL (*PREGISTERURBDRCSERVICE)(IWTSPlugin* plugin, IUDEVMAN* udevman);
@ -174,6 +175,7 @@ struct _IUDEVICE
void (*setAlreadySend)(IUDEVICE* idev);
void (*setChannelClosed)(IUDEVICE* idev);
void (*markChannelClosed)(IUDEVICE* idev);
char* (*getPath)(IUDEVICE* idev);
void (*free)(IUDEVICE* idev);
@ -205,6 +207,7 @@ struct _IUDEVMAN
UINT16 idProduct, UINT32 flag);
IUDEVICE* (*get_next)(IUDEVMAN* idevman);
IUDEVICE* (*get_udevice_by_UsbDevice)(IUDEVMAN* idevman, UINT32 UsbDevice);
IUDEVICE* (*get_udevice_by_ChannelID)(IUDEVMAN* idevman, UINT32 channelID);
/* Extension */
int (*isAutoAdd)(IUDEVMAN* idevman);

View File

@ -391,7 +391,7 @@ void urbdrc_dump_message(wLog* log, BOOL client, BOOL write, wStream* s)
pos = Stream_GetPosition(s);
if (write)
{
length = Stream_GetPosition(s);
length = pos;
Stream_SetPosition(s, 0);
}
else
@ -407,7 +407,7 @@ void urbdrc_dump_message(wLog* log, BOOL client, BOOL write, wStream* s)
WLog_Print(log, WLOG_DEBUG,
"[%-5s] %s [%08" PRIx32 "] InterfaceId=%08" PRIx32 ", MessageId=%08" PRIx32
", FunctionId=%08" PRIx32 ", length=%" PRIdz,
", FunctionId=%08" PRIx32 ", length=%" PRIuz,
type, call_to_string(client, InterfaceId, FunctionId), FunctionId, InterfaceId,
MessageId, FunctionId, length);
#if defined(WITH_DEBUG_URBDRC)

View File

@ -76,6 +76,7 @@ struct _VIDEO_PLUGIN
VIDEO_LISTENER_CALLBACK* data_callback;
VideoClientContext* context;
BOOL initialized;
};
typedef struct _VIDEO_PLUGIN VIDEO_PLUGIN;
@ -1035,6 +1036,11 @@ static UINT video_plugin_initialize(IWTSPlugin* plugin, IWTSVirtualChannelManage
VIDEO_PLUGIN* video = (VIDEO_PLUGIN*)plugin;
VIDEO_LISTENER_CALLBACK* callback;
if (video->initialized)
{
WLog_ERR(TAG, "[%s] channel initialized twice, aborting", VIDEO_CONTROL_DVC_CHANNEL_NAME);
return ERROR_INVALID_DATA;
}
video->control_callback = callback =
(VIDEO_LISTENER_CALLBACK*)calloc(1, sizeof(VIDEO_LISTENER_CALLBACK));
if (!callback)
@ -1072,6 +1078,7 @@ static UINT video_plugin_initialize(IWTSPlugin* plugin, IWTSVirtualChannelManage
if (status == CHANNEL_RC_OK)
video->dataListener->pInterface = video->wtsPlugin.pInterface;
video->initialized = status == CHANNEL_RC_OK;
return status;
}

View File

@ -1,6 +1,7 @@
message("PRELOADING android cache")
message("PRELOADING iOS cache")
set (CMAKE_TOOLCHAIN_FILE "cmake/iOSToolchain.cmake" CACHE PATH "ToolChain file")
set (FREERDP_IOS_EXTERNAL_SSL_PATH $ENV{FREERDP_IOS_EXTERNAL_SSL_PATH} CACHE PATH "android ssl")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (IOS_PLATFORM "SIMULATOR" CACHE STRING "iso platfrorm to build")
set (WITH_SANITIZE_ADDRESS ON)
set (WITH_SANITIZE_ADDRESS ON CACHE BOOL "build with address sanitizer")
set (WITH_CLIENT OFF CACHE BOOL "disable iOS client")

View File

@ -7,6 +7,7 @@ set (WITH_PULSE ON CACHE BOOL "pulse")
set (WITH_CHANNELS ON CACHE BOOL "channels")
set (BUILTIN_CHANNELS ON CACHE BOOL "static channels")
set (WITH_CUPS ON CACHE BOOL "cups")
set (WITH_WAYLAND ON CACHE BOOL "wayland")
set (WITH_GSSAPI ON CACHE BOOL "Kerberos support")
set (WITH_PCSC ON CACHE BOOL "PCSC")
set (WITH_JPEG ON CACHE BOOL "jpeg")

View File

@ -338,12 +338,10 @@ int main(int argc, char* argv[])
goto fail;
status = freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE);
status =
freerdp_client_settings_command_line_status_print(context->settings, status, argc, argv);
if (status)
{
rc = 0;
rc = freerdp_client_settings_command_line_status_print(context->settings, status, argc,
argv);
goto fail;
}

View File

@ -306,7 +306,8 @@ static UINT wlf_cliprdr_send_client_capabilities(wfClipboard* clipboard)
generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
if (clipboard->streams_supported && clipboard->file_formats_registered)
generalCapabilitySet.generalFlags |= CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS;
generalCapabilitySet.generalFlags |=
CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS | CB_HUGE_FILE_SUPPORT_ENABLED;
return clipboard->context->ClientCapabilities(clipboard->context, &capabilities);
}

View File

@ -137,9 +137,9 @@ BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev)
{
rdpInput* input;
UINT16 flags = 0;
int direction;
uint32_t step;
int32_t direction;
uint32_t x, y;
uint32_t i;
if (!instance || !ev || !instance->input)
return FALSE;
@ -152,7 +152,7 @@ BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev)
input = instance->input;
direction = wl_fixed_to_int(ev->value);
direction = ev->value;
switch (ev->axis)
{
case WL_POINTER_AXIS_VERTICAL_SCROLL:
@ -176,17 +176,17 @@ BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev)
* positive: 0 ... 0xFF -> slow ... fast
* negative: 0 ... 0xFF -> fast ... slow
*/
step = abs(direction);
if (step > 0xFF)
step = 0xFF;
for (i = 0; i < abs(direction); i++)
{
uint32_t cflags = flags | 0x78;
/* Convert negative values to 9bit twos complement */
if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
cflags = (flags & 0xFF00) | (0x100 - (cflags & 0xFF));
if (!freerdp_input_send_mouse_event(input, cflags, (UINT16)x, (UINT16)y))
return FALSE;
}
/* Negative rotation, so count down steps from top */
if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
step = 0xFF - step;
flags |= step;
return freerdp_input_send_mouse_event(input, flags, (UINT16)x, (UINT16)y);
return TRUE;
}
BOOL wlf_handle_key(freerdp* instance, const UwacKeyEvent* ev)
@ -207,14 +207,35 @@ BOOL wlf_handle_key(freerdp* instance, const UwacKeyEvent* ev)
}
BOOL wlf_keyboard_enter(freerdp* instance, const UwacKeyboardEnterLeaveEvent* ev)
{
if (!instance || !ev || !instance->input)
return FALSE;
((wlfContext*)instance->context)->focusing = TRUE;
return TRUE;
}
BOOL wlf_keyboard_modifiers(freerdp* instance, const UwacKeyboardModifiersEvent* ev)
{
rdpInput* input;
uint32_t syncFlags;
if (!instance || !ev || !instance->input)
return FALSE;
input = instance->input;
return freerdp_input_send_focus_in_event(input, 0) &&
syncFlags = 0;
if (ev->modifiers & UWAC_MOD_CAPS_MASK)
syncFlags |= KBD_SYNC_CAPS_LOCK;
if (ev->modifiers & UWAC_MOD_NUM_MASK)
syncFlags |= KBD_SYNC_NUM_LOCK;
if (!((wlfContext*)instance->context)->focusing)
return TRUE;
((wlfContext*)instance->context)->focusing = FALSE;
return freerdp_input_send_focus_in_event(input, syncFlags) &&
freerdp_input_send_mouse_event(input, PTR_FLAGS_MOVE, 0, 0);
}

View File

@ -36,5 +36,6 @@ BOOL wlf_handle_touch_motion(freerdp* instance, const UwacTouchMotion* ev);
BOOL wlf_handle_key(freerdp* instance, const UwacKeyEvent* ev);
BOOL wlf_keyboard_enter(freerdp* instance, const UwacKeyboardEnterLeaveEvent* ev);
BOOL wlf_keyboard_modifiers(freerdp* instance, const UwacKeyboardModifiersEvent* ev);
#endif /* FREERDP_CLIENT_WAYLAND_INPUT_H */

View File

@ -270,7 +270,8 @@ static BOOL wl_post_connect(freerdp* instance)
instance->update->BeginPaint = wl_begin_paint;
instance->update->EndPaint = wl_end_paint;
instance->update->DesktopResize = wl_resize_display;
freerdp_keyboard_init(instance->context->settings->KeyboardLayout);
freerdp_keyboard_init_ex(instance->context->settings->KeyboardLayout,
instance->context->settings->KeyboardRemappingList);
if (!(context->disp = wlf_disp_new(context)))
return FALSE;
@ -356,6 +357,9 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
break;
case UWAC_EVENT_POINTER_AXIS:
break;
case UWAC_EVENT_POINTER_AXIS_DISCRETE:
if (!wlf_handle_pointer_axis(instance, &event.mouse_axis))
return FALSE;
@ -394,6 +398,12 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
break;
case UWAC_EVENT_KEYBOARD_MODIFIERS:
if (!wlf_keyboard_modifiers(instance, &event.keyboard_modifiers))
return FALSE;
break;
case UWAC_EVENT_CONFIGURE:
if (!wlf_disp_handle_configure(context->disp, event.configure.width,
event.configure.height))
@ -412,6 +422,11 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
break;
case UWAC_EVENT_CLOSE:
context->closed = TRUE;
break;
default:
break;
}
@ -482,6 +497,12 @@ static int wlfreerdp_run(freerdp* instance)
break;
}
if (context->closed)
{
WLog_Print(context->log, WLOG_INFO, "Closed from Wayland");
break;
}
if (freerdp_check_event_handles(instance->context) != TRUE)
{
if (client_auto_reconnect_ex(instance, handle_window_events))
@ -550,6 +571,7 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context)
instance->GatewayAuthenticate = client_cli_gw_authenticate;
instance->VerifyCertificateEx = client_cli_verify_certificate_ex;
instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex;
instance->PresentGatewayMessage = client_cli_present_gateway_message;
instance->LogonErrorInfo = wlf_logon_error_info;
wfl->log = WLog_Get(TAG);
wfl->display = UwacOpenDisplay(NULL, &status);
@ -627,18 +649,16 @@ int main(int argc, char* argv[])
settings = context->settings;
status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE);
status = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
if (status)
{
BOOL list = settings->ListMonitors;
rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
if (list)
wlf_list_monitors(wlc);
freerdp_client_context_free(context);
if (list)
return 0;
return status;
goto fail;
}
if (freerdp_client_start(context) != 0)

View File

@ -42,6 +42,8 @@ struct wlf_context
UwacSeat* seat;
BOOL fullscreen;
BOOL closed;
BOOL focusing;
/* Channels */
RdpeiClientContext* rdpei;

View File

@ -34,6 +34,7 @@
int main(int argc, char* argv[])
{
int rc = 1;
int status;
HANDLE thread;
xfContext* xfc;
@ -56,31 +57,31 @@ int main(int argc, char* argv[])
xfc = (xfContext*)context;
status = freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE);
status = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
if (status)
{
BOOL list = settings->ListMonitors;
rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
if (list)
xf_list_monitors(xfc);
freerdp_client_context_free(context);
if (list)
return 0;
return status;
goto out;
}
freerdp_client_start(context);
if (freerdp_client_start(context) != 0)
goto out;
thread = freerdp_client_get_thread(context);
WaitForSingleObject(thread, INFINITE);
GetExitCodeThread(thread, &dwExitCode);
rc = xf_exit_code_from_disconnect_reason(dwExitCode);
freerdp_client_stop(context);
out:
freerdp_client_context_free(context);
return xf_exit_code_from_disconnect_reason(dwExitCode);
return rc;
}

View File

@ -244,7 +244,8 @@ int main(int argc, char* argv[])
if (text)
fprintf(fp, "%s", text);
if (arg->Flags == COMMAND_LINE_VALUE_BOOL)
if (arg->Flags & COMMAND_LINE_VALUE_BOOL &&
(!arg->Default || arg->Default == BoolValueTrue))
fprintf(fp, " (default:%s)", arg->Default ? "on" : "off");
else if (arg->Default)
{

View File

@ -299,8 +299,8 @@ static BOOL xf_desktop_resize(rdpContext* context)
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetForeground(xfc->display, xfc->gc, 0);
XFillRectangle(xfc->display, xfc->drawable, xfc->gc, 0, 0, xfc->window->width,
xfc->window->height);
XFillRectangle(xfc->display, xfc->drawable, xfc->gc, 0, 0, settings->DesktopWidth,
settings->DesktopHeight);
}
return TRUE;
@ -940,6 +940,7 @@ static int _xf_error_handler(Display* d, XErrorEvent* ev)
* another window. This make xf_error_handler() a potential
* debugger breakpoint.
*/
XUngrabKeyboard(d, CurrentTime);
return xf_error_handler(d, ev);
}
@ -1075,8 +1076,9 @@ static const button_map xf_button_flags[NUM_BUTTONS_MAPPED] = {
{ Button2, PTR_FLAGS_BUTTON3 },
{ Button3, PTR_FLAGS_BUTTON2 },
{ Button4, PTR_FLAGS_WHEEL | 0x78 },
{ Button5, PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x78 },
{ 6, PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x78 },
/* Negative value is 9bit twos complement */
{ Button5, PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | (0x100 - 0x78) },
{ 6, PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | (0x100 - 0x78) },
{ 7, PTR_FLAGS_HWHEEL | 0x78 },
{ 8, PTR_XFLAGS_BUTTON1 },
{ 9, PTR_XFLAGS_BUTTON2 },
@ -1837,6 +1839,7 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
instance->GatewayAuthenticate = client_cli_gw_authenticate;
instance->VerifyCertificateEx = client_cli_verify_certificate_ex;
instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex;
instance->PresentGatewayMessage = client_cli_present_gateway_message;
instance->LogonErrorInfo = xf_logon_error_info;
PubSub_SubscribeTerminate(context->pubSub, xf_TerminateEventHandler);
#ifdef WITH_XRENDER
@ -1885,9 +1888,9 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
if ((xfc->_NET_SUPPORTED != None) && (xfc->_NET_SUPPORTING_WM_CHECK != None))
{
Atom actual_type;
int actual_format;
unsigned long nitems, after;
Atom actual_type = 0;
int actual_format = 0;
unsigned long nitems = 0, after = 0;
unsigned char* data = NULL;
int status = XGetWindowProperty(xfc->display, RootWindowOfScreen(xfc->screen),
xfc->_NET_SUPPORTED, 0, 1024, False, XA_ATOM, &actual_type,
@ -1904,6 +1907,8 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
XFree(data);
}
xfc->_XWAYLAND_MAY_GRAB_KEYBOARD =
XInternAtom(xfc->display, "_XWAYLAND_MAY_GRAB_KEYBOARD", False);
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);

View File

@ -68,6 +68,9 @@ struct xf_clipboard
Atom clipboard_atom;
Atom property_atom;
Atom timestamp_property_atom;
Time selection_ownership_timestamp;
Atom raw_transfer_atom;
Atom raw_format_list_atom;
@ -108,9 +111,14 @@ struct xf_clipboard
/* File clipping */
BOOL streams_supported;
BOOL file_formats_registered;
UINT32 file_capability_flags;
/* last sent data */
CLIPRDR_FORMAT* lastSentFormats;
UINT32 lastSentNumFormats;
};
static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard);
static void xf_cliprdr_set_selection_owner(xfContext* xfc, xfClipboard* clipboard, Time timestamp);
static void xf_cliprdr_check_owner(xfClipboard* clipboard)
{
@ -268,9 +276,17 @@ static UINT xf_cliprdr_send_data_request(xfClipboard* clipboard, UINT32 formatId
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT xf_cliprdr_send_data_response(xfClipboard* clipboard, BYTE* data, int size)
static UINT xf_cliprdr_send_data_response(xfClipboard* clipboard, const BYTE* data, size_t size)
{
CLIPRDR_FORMAT_DATA_RESPONSE response = { 0 };
/* No request currently pending, do not send a response. */
if (clipboard->requestedFormatId < 0)
return CHANNEL_RC_OK;
/* Request handled, reset to invalid */
clipboard->requestedFormatId = -1;
response.msgFlags = (data) ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
response.dataLen = size;
response.requestedFormatData = data;
@ -524,17 +540,92 @@ static void xf_cliprdr_provide_server_format_list(xfClipboard* clipboard)
Stream_Free(formats, TRUE);
}
static BOOL xf_clipboard_format_equal(const CLIPRDR_FORMAT* a, const CLIPRDR_FORMAT* b)
{
if (a->formatId != b->formatId)
return FALSE;
if (!a->formatName && !b->formatName)
return TRUE;
return strcmp(a->formatName, b->formatName) == 0;
}
static BOOL xf_clipboard_changed(xfClipboard* clipboard, const CLIPRDR_FORMAT* formats,
UINT32 numFormats)
{
UINT32 x, y;
if (clipboard->lastSentNumFormats != numFormats)
return TRUE;
for (x = 0; x < numFormats; x++)
{
const CLIPRDR_FORMAT* cur = &clipboard->lastSentFormats[x];
BOOL contained = FALSE;
for (y = 0; y < numFormats; y++)
{
if (xf_clipboard_format_equal(cur, &formats[y]))
{
contained = TRUE;
break;
}
}
if (!contained)
return TRUE;
}
return FALSE;
}
static void xf_clipboard_formats_free(xfClipboard* clipboard)
{
xf_cliprdr_free_formats(clipboard->lastSentFormats, clipboard->lastSentNumFormats);
clipboard->lastSentFormats = NULL;
clipboard->lastSentNumFormats = 0;
}
static BOOL xf_clipboard_copy_formats(xfClipboard* clipboard, const CLIPRDR_FORMAT* formats,
UINT32 numFormats)
{
UINT32 x;
xf_clipboard_formats_free(clipboard);
clipboard->lastSentFormats = calloc(numFormats, sizeof(CLIPRDR_FORMAT));
if (!clipboard->lastSentFormats)
return FALSE;
clipboard->lastSentNumFormats = numFormats;
for (x = 0; x < numFormats; x++)
{
CLIPRDR_FORMAT* lcur = &clipboard->lastSentFormats[x];
const CLIPRDR_FORMAT* cur = &formats[x];
*lcur = *cur;
if (cur->formatName)
lcur->formatName = _strdup(cur->formatName);
}
return FALSE;
}
static UINT xf_cliprdr_send_format_list(xfClipboard* clipboard, const CLIPRDR_FORMAT* formats,
UINT32 numFormats)
{
CLIPRDR_FORMAT_LIST formatList = { 0 };
formatList.msgFlags = CB_RESPONSE_OK;
formatList.numFormats = numFormats;
formatList.formats = (CLIPRDR_FORMAT*)formats;
formatList.msgType = CB_FORMAT_LIST;
if (!xf_clipboard_changed(clipboard, formats, numFormats))
return CHANNEL_RC_OK;
xf_clipboard_copy_formats(clipboard, formats, numFormats);
/* Ensure all pending requests are answered. */
xf_cliprdr_send_data_response(clipboard, NULL, 0);
return clipboard->context->ClientFormatList(clipboard->context, &formatList);
}
static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
{
UINT32 numFormats = 0;
CLIPRDR_FORMAT* formats = NULL;
CLIPRDR_FORMAT_LIST formatList = { 0 };
formats = xf_cliprdr_get_client_formats(clipboard, &numFormats);
formatList.msgFlags = CB_RESPONSE_OK;
formatList.numFormats = numFormats;
formatList.formats = formats;
formatList.msgType = CB_FORMAT_LIST;
clipboard->context->ClientFormatList(clipboard->context, &formatList);
xf_cliprdr_send_format_list(clipboard, formats, numFormats);
xf_cliprdr_free_formats(formats, numFormats);
}
@ -619,11 +710,12 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
(dstFormatId == ClipboardGetFormatId(clipboard->system, "FileGroupDescriptorW")))
{
UINT error = NO_ERROR;
FILEDESCRIPTOR* file_array = (FILEDESCRIPTOR*)pDstData;
UINT32 file_count = DstSize / sizeof(FILEDESCRIPTOR);
FILEDESCRIPTORW* file_array = (FILEDESCRIPTORW*)pDstData;
UINT32 file_count = DstSize / sizeof(FILEDESCRIPTORW);
pDstData = NULL;
DstSize = 0;
error = cliprdr_serialize_file_list(file_array, file_count, &pDstData, &DstSize);
error = cliprdr_serialize_file_list_ex(clipboard->file_capability_flags, file_array,
file_count, &pDstData, &DstSize);
if (error)
WLog_ERR(TAG, "failed to serialize CLIPRDR_FILELIST: 0x%08X", error);
@ -631,7 +723,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
free(file_array);
}
xf_cliprdr_send_data_response(clipboard, pDstData, (int)DstSize);
xf_cliprdr_send_data_response(clipboard, pDstData, DstSize);
free(pDstData);
}
@ -646,6 +738,7 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
unsigned long bytes_left;
xfCliprdrFormat* format;
xfContext* xfc = clipboard->xfc;
format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId);
if (!format || (format->atom != target))
@ -702,14 +795,16 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
new_data =
(BYTE*)realloc(clipboard->incr_data, clipboard->incr_data_length + bytes_left);
if (!new_data)
return FALSE;
if (new_data)
{
clipboard->incr_data = new_data;
CopyMemory(clipboard->incr_data + clipboard->incr_data_length, data, bytes_left);
clipboard->incr_data_length += bytes_left;
XFree(data);
data = NULL;
clipboard->incr_data = new_data;
CopyMemory(clipboard->incr_data + clipboard->incr_data_length, data,
bytes_left);
clipboard->incr_data_length += bytes_left;
XFree(data);
data = NULL;
}
}
has_data = TRUE;
@ -720,7 +815,7 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
}
XDeleteProperty(xfc->display, xfc->drawable, clipboard->property_atom);
xf_cliprdr_process_requested_data(clipboard, has_data, data, (int)bytes_left);
xf_cliprdr_process_requested_data(clipboard, has_data, data, bytes_left);
if (data)
XFree(data);
@ -758,6 +853,17 @@ static void xf_cliprdr_provide_targets(xfClipboard* clipboard, const XSelectionE
}
}
static void xf_cliprdr_provide_timestamp(xfClipboard* clipboard, const XSelectionEvent* respond)
{
xfContext* xfc = clipboard->xfc;
if (respond->property != None)
{
XChangeProperty(xfc->display, respond->requestor, respond->property, XA_INTEGER, 32,
PropModeReplace, (BYTE*)&clipboard->selection_ownership_timestamp, 1);
}
}
static void xf_cliprdr_provide_data(xfClipboard* clipboard, const XSelectionEvent* respond,
const BYTE* data, UINT32 size)
{
@ -849,7 +955,9 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard,
if (xevent->target == clipboard->targets[0]) /* TIMESTAMP */
{
/* TODO */
/* Someone else requests the selection's timestamp */
respond->property = xevent->property;
xf_cliprdr_provide_timestamp(clipboard, respond);
}
else if (xevent->target == clipboard->targets[1]) /* TARGETS */
{
@ -964,6 +1072,16 @@ static BOOL xf_cliprdr_process_property_notify(xfClipboard* clipboard, const XPr
xfc = clipboard->xfc;
if (xevent->atom == clipboard->timestamp_property_atom)
{
/* This is the response to the property change we did
* in xf_cliprdr_prepare_to_set_selection_owner. Now
* we can set ourselves as the selection owner. (See
* comments in those functions below.) */
xf_cliprdr_set_selection_owner(xfc, clipboard, xevent->time);
return TRUE;
}
if (xevent->atom != clipboard->property_atom)
return FALSE; /* Not cliprdr-related */
@ -1064,8 +1182,10 @@ static UINT xf_cliprdr_send_client_capabilities(xfClipboard* clipboard)
generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
if (clipboard->streams_supported && clipboard->file_formats_registered)
generalCapabilitySet.generalFlags |= CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS;
generalCapabilitySet.generalFlags |=
CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS | CB_HUGE_FILE_SUPPORT_ENABLED;
clipboard->file_capability_flags = generalCapabilitySet.generalFlags;
return clipboard->context->ClientCapabilities(clipboard->context, &capabilities);
}
@ -1078,7 +1198,6 @@ static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard)
{
UINT32 i, numFormats;
CLIPRDR_FORMAT* formats = NULL;
CLIPRDR_FORMAT_LIST formatList = { 0 };
xfContext* xfc = clipboard->xfc;
UINT ret;
numFormats = clipboard->numClientFormats;
@ -1098,11 +1217,7 @@ static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard)
formats[i].formatName = clipboard->clientFormats[i].formatName;
}
formatList.msgFlags = CB_RESPONSE_OK;
formatList.numFormats = numFormats;
formatList.formats = formats;
formatList.msgType = CB_FORMAT_LIST;
ret = clipboard->context->ClientFormatList(clipboard->context, &formatList);
ret = xf_cliprdr_send_format_list(clipboard, formats, numFormats);
free(formats);
if (clipboard->owner && clipboard->owner != xfc->drawable)
@ -1187,6 +1302,43 @@ static UINT xf_cliprdr_server_capabilities(CliprdrClientContext* context,
return CHANNEL_RC_OK;
}
static void xf_cliprdr_prepare_to_set_selection_owner(xfContext* xfc, xfClipboard* clipboard)
{
/*
* When you're writing to the selection in response to a
* normal X event like a mouse click or keyboard action, you
* get the selection timestamp by copying the time field out
* of that X event. Here, we're doing it on our own
* initiative, so we have to _request_ the X server time.
*
* There isn't a GetServerTime request in the X protocol, so I
* work around it by setting a property on our own window, and
* waiting for a PropertyNotify event to come back telling me
* it's been done - which will have a timestamp we can use.
*/
/* We have to set the property to some value, but it doesn't
* matter what. Set it to its own name, which we have here
* anyway! */
Atom value = clipboard->timestamp_property_atom;
XChangeProperty(xfc->display, xfc->drawable, clipboard->timestamp_property_atom, XA_ATOM, 32,
PropModeReplace, (BYTE*)&value, 1);
XFlush(xfc->display);
}
static void xf_cliprdr_set_selection_owner(xfContext* xfc, xfClipboard* clipboard, Time timestamp)
{
/*
* Actually set ourselves up as the selection owner, now that
* we have a timestamp to use.
*/
clipboard->selection_ownership_timestamp = timestamp;
XSetSelectionOwner(xfc->display, clipboard->clipboard_atom, xfc->drawable, timestamp);
XFlush(xfc->display);
}
/**
* Function description
*
@ -1200,6 +1352,7 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context,
xfClipboard* clipboard = (xfClipboard*)context->custom;
xfContext* xfc = clipboard->xfc;
UINT ret;
xf_clipboard_formats_free(clipboard);
xf_cliprdr_clear_cached_data(clipboard);
clipboard->data_format_id = -1;
clipboard->data_format_name = NULL;
@ -1270,8 +1423,7 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context,
}
ret = xf_cliprdr_send_client_format_list_response(clipboard, TRUE);
XSetSelectionOwner(xfc->display, clipboard->clipboard_atom, xfc->drawable, CurrentTime);
XFlush(xfc->display);
xf_cliprdr_prepare_to_set_selection_owner(xfc, clipboard);
return ret;
}
@ -1313,10 +1465,10 @@ xf_cliprdr_server_format_data_request(CliprdrClientContext* context,
else
format = xf_cliprdr_get_client_format_by_id(clipboard, formatId);
clipboard->requestedFormatId = rawTransfer ? CF_RAW : formatId;
if (!format)
return xf_cliprdr_send_data_response(clipboard, NULL, 0);
clipboard->requestedFormatId = rawTransfer ? CF_RAW : formatId;
XConvertSelection(xfc->display, clipboard->clipboard_atom, format->atom,
clipboard->property_atom, xfc->drawable, CurrentTime);
XFlush(xfc->display);
@ -1604,6 +1756,7 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
int i, n = 0;
rdpChannels* channels;
xfClipboard* clipboard;
const char* selectionAtom;
if (!(clipboard = (xfClipboard*)calloc(1, sizeof(xfClipboard))))
{
@ -1618,14 +1771,19 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
clipboard->system = ClipboardCreate();
clipboard->requestedFormatId = -1;
clipboard->root_window = DefaultRootWindow(xfc->display);
clipboard->clipboard_atom = XInternAtom(xfc->display, "CLIPBOARD", FALSE);
selectionAtom = "CLIPBOARD";
if (xfc->context.settings->XSelectionAtom)
selectionAtom = xfc->context.settings->XSelectionAtom;
clipboard->clipboard_atom = XInternAtom(xfc->display, selectionAtom, FALSE);
if (clipboard->clipboard_atom == None)
{
WLog_ERR(TAG, "unable to get CLIPBOARD atom");
WLog_ERR(TAG, "unable to get %s atom", selectionAtom);
goto error;
}
clipboard->timestamp_property_atom =
XInternAtom(xfc->display, "_FREERDP_TIMESTAMP_PROPERTY", FALSE);
clipboard->property_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR", FALSE);
clipboard->raw_transfer_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR_RAW", FALSE);
clipboard->raw_format_list_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR_FORMATS", FALSE);
@ -1756,6 +1914,7 @@ void xf_clipboard_free(xfClipboard* clipboard)
}
ClipboardDestroy(clipboard->system);
xf_clipboard_formats_free(clipboard);
free(clipboard->data);
free(clipboard->data_raw);
free(clipboard->respond);

View File

@ -46,7 +46,6 @@ struct _xfDispContext
UINT64 lastSentDate;
int targetWidth, targetHeight;
BOOL activated;
BOOL waitingResize;
BOOL fullscreen;
UINT16 lastSentDesktopOrientation;
UINT32 lastSentDesktopScaleFactor;
@ -113,11 +112,10 @@ static BOOL xf_disp_sendResize(xfDispContext* xfDisp)
if (GetTickCount64() - xfDisp->lastSentDate < RESIZE_MIN_DELAY)
return TRUE;
xfDisp->lastSentDate = GetTickCount64();
if (!xf_disp_settings_changed(xfDisp))
return TRUE;
xfDisp->lastSentDate = GetTickCount64();
if (xfc->fullscreen && (settings->MonitorCount > 0))
{
if (xf_disp_sendLayout(xfDisp->disp, settings->MonitorDefArray, settings->MonitorCount) !=
@ -126,7 +124,6 @@ static BOOL xf_disp_sendResize(xfDispContext* xfDisp)
}
else
{
xfDisp->waitingResize = TRUE;
layout.Flags = DISPLAY_CONTROL_MONITOR_PRIMARY;
layout.Top = layout.Left = 0;
layout.Width = xfDisp->targetWidth;
@ -134,8 +131,8 @@ static BOOL xf_disp_sendResize(xfDispContext* xfDisp)
layout.Orientation = settings->DesktopOrientation;
layout.DesktopScaleFactor = settings->DesktopScaleFactor;
layout.DeviceScaleFactor = settings->DeviceScaleFactor;
layout.PhysicalWidth = xfDisp->targetWidth;
layout.PhysicalHeight = xfDisp->targetHeight;
layout.PhysicalWidth = xfDisp->targetWidth / 75 * 25.4f;
layout.PhysicalHeight = xfDisp->targetHeight / 75 * 25.4f;
if (IFCALLRESULT(CHANNEL_RC_OK, xfDisp->disp->SendMonitorLayout, xfDisp->disp, 1,
&layout) != CHANNEL_RC_OK)
@ -145,6 +142,16 @@ static BOOL xf_disp_sendResize(xfDispContext* xfDisp)
return xf_update_last_sent(xfDisp);
}
static BOOL xf_disp_queueResize(xfDispContext* xfDisp, UINT32 width, UINT32 height)
{
if ((xfDisp->targetWidth == width) && (xfDisp->targetHeight == height))
return TRUE;
xfDisp->targetWidth = width;
xfDisp->targetHeight = height;
xfDisp->lastSentDate = GetTickCount64();
return xf_disp_sendResize(xfDisp);
}
static BOOL xf_disp_set_window_resizable(xfDispContext* xfDisp)
{
XSizeHints* size_hints;
@ -195,9 +202,7 @@ static void xf_disp_OnActivated(void* context, ActivatedEventArgs* e)
if (!xf_disp_check_context(context, &xfc, &xfDisp, &settings))
return;
xfDisp->waitingResize = FALSE;
if (xfDisp->activated && !settings->Fullscreen)
if (xfDisp->activated && !xfc->fullscreen)
{
xf_disp_set_window_resizable(xfDisp);
@ -219,8 +224,6 @@ static void xf_disp_OnGraphicsReset(void* context, GraphicsResetEventArgs* e)
if (!xf_disp_check_context(context, &xfc, &xfDisp, &settings))
return;
xfDisp->waitingResize = FALSE;
if (xfDisp->activated && !settings->Fullscreen)
{
xf_disp_set_window_resizable(xfDisp);
@ -393,9 +396,7 @@ BOOL xf_disp_handle_configureNotify(xfContext* xfc, int width, int height)
if (!xfDisp)
return FALSE;
xfDisp->targetWidth = width;
xfDisp->targetHeight = height;
return xf_disp_sendResize(xfDisp);
return xf_disp_queueResize(xfDisp, width, height);
}
static UINT xf_DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors,

View File

@ -503,6 +503,10 @@ static BOOL xf_event_FocusIn(xfContext* xfc, const XFocusInEvent* event, BOOL ap
CurrentTime);
}
/* Release all keys, should already be done at FocusOut but might be missed
* if the WM decided to use an alternate event order */
xf_keyboard_release_all_keypress(xfc);
if (app)
{
xfAppWindow* appWindow;
@ -532,7 +536,6 @@ static BOOL xf_event_FocusOut(xfContext* xfc, const XFocusOutEvent* event, BOOL
XUngrabKeyboard(xfc->display, CurrentTime);
xf_keyboard_release_all_keypress(xfc);
xf_keyboard_clear(xfc);
if (app)
xf_rail_send_activate(xfc, event->window, FALSE);
@ -600,15 +603,10 @@ static BOOL xf_event_EnterNotify(xfContext* xfc, const XEnterWindowEvent* event,
}
else
{
xfAppWindow* appWindow;
appWindow = xf_AppWindowFromX11Window(xfc, event->window);
xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
/* keep track of which window has focus so that we can apply pointer updates */
if (appWindow)
{
xfc->appWindow = appWindow;
}
xfc->appWindow = appWindow;
}
return TRUE;
@ -616,14 +614,19 @@ static BOOL xf_event_EnterNotify(xfContext* xfc, const XEnterWindowEvent* event,
static BOOL xf_event_LeaveNotify(xfContext* xfc, const XLeaveWindowEvent* event, BOOL app)
{
WINPR_UNUSED(event);
if (!app)
{
xfc->mouse_active = FALSE;
XUngrabKeyboard(xfc->display, CurrentTime);
}
else
{
xfAppWindow* appWindow = xf_AppWindowFromX11Window(xfc, event->window);
/* keep track of which window has focus so that we can apply pointer updates */
if (xfc->appWindow == appWindow)
xfc->appWindow = NULL;
}
return TRUE;
}

View File

@ -226,13 +226,156 @@ static BOOL xf_Bitmap_SetSurface(rdpContext* context, rdpBitmap* bitmap, BOOL pr
return TRUE;
}
static BOOL _xf_Pointer_GetCursorForCurrentScale(rdpContext* context, const rdpPointer* pointer,
Cursor* cursor)
{
#ifdef WITH_XCURSOR
UINT32 CursorFormat;
xfContext* xfc = (xfContext*)context;
xfPointer* xpointer = (xfPointer*)pointer;
XcursorImage ci;
rdpSettings* settings;
UINT32 xTargetSize;
UINT32 yTargetSize;
double xscale;
double yscale;
size_t size;
int cursorIndex = -1;
if (!context || !pointer || !context->gdi)
return FALSE;
settings = xfc->context.settings;
if (!settings)
return FALSE;
xscale = (settings->SmartSizing ? xfc->scaledWidth / (double)settings->DesktopWidth : 1);
yscale = (settings->SmartSizing ? xfc->scaledHeight / (double)settings->DesktopHeight : 1);
xTargetSize = pointer->width * xscale;
yTargetSize = pointer->height * yscale;
for (int i = 0; i < xpointer->nCursors; i++)
{
if (xpointer->cursorWidths[i] == xTargetSize && xpointer->cursorHeights[i] == yTargetSize)
{
cursorIndex = i;
}
}
if (cursorIndex == -1)
{
xf_lock_x11(xfc);
if (!xfc->invert)
CursorFormat = (!xfc->big_endian) ? PIXEL_FORMAT_RGBA32 : PIXEL_FORMAT_ABGR32;
else
CursorFormat = (!xfc->big_endian) ? PIXEL_FORMAT_BGRA32 : PIXEL_FORMAT_ARGB32;
if (xpointer->nCursors == xpointer->mCursors)
{
xpointer->mCursors = (xpointer->mCursors == 0 ? 1 : xpointer->mCursors * 2);
if (!(xpointer->cursorWidths = (UINT32*)realloc(xpointer->cursorWidths,
sizeof(UINT32) * xpointer->mCursors)))
{
xf_unlock_x11(xfc);
return FALSE;
}
if (!(xpointer->cursorHeights = (UINT32*)realloc(xpointer->cursorHeights,
sizeof(UINT32) * xpointer->mCursors)))
{
xf_unlock_x11(xfc);
return FALSE;
}
if (!(xpointer->cursors =
(Cursor*)realloc(xpointer->cursors, sizeof(Cursor) * xpointer->mCursors)))
{
xf_unlock_x11(xfc);
return FALSE;
}
}
ZeroMemory(&ci, sizeof(ci));
ci.version = XCURSOR_IMAGE_VERSION;
ci.size = sizeof(ci);
ci.width = xTargetSize;
ci.height = yTargetSize;
ci.xhot = pointer->xPos * xscale;
ci.yhot = pointer->yPos * yscale;
size = ci.height * ci.width * GetBytesPerPixel(CursorFormat);
if (!(ci.pixels = (XcursorPixel*)_aligned_malloc(size, 16)))
{
xf_unlock_x11(xfc);
return FALSE;
}
if (xscale != 1 || yscale != 1)
{
if (!freerdp_image_scale((BYTE*)ci.pixels, CursorFormat, 0, 0, 0, ci.width, ci.height,
(BYTE*)xpointer->cursorPixels, CursorFormat, 0, 0, 0,
pointer->width, pointer->height))
{
_aligned_free(ci.pixels);
xf_unlock_x11(xfc);
return FALSE;
}
}
else
{
ci.pixels = xpointer->cursorPixels;
}
cursorIndex = xpointer->nCursors;
xpointer->cursorWidths[cursorIndex] = ci.width;
xpointer->cursorHeights[cursorIndex] = ci.height;
xpointer->cursors[cursorIndex] = XcursorImageLoadCursor(xfc->display, &ci);
xpointer->nCursors += 1;
if (xscale != 1 || yscale != 1)
_aligned_free(ci.pixels);
xf_unlock_x11(xfc);
}
cursor[0] = xpointer->cursors[cursorIndex];
#endif
return TRUE;
}
/* Pointer Class */
static Window xf_Pointer_get_window(xfContext* xfc)
{
if (!xfc)
{
WLog_WARN(TAG, "xf_Pointer: Invalid context");
return 0;
}
if (xfc->remote_app)
{
if (!xfc->appWindow)
{
WLog_WARN(TAG, "xf_Pointer: Invalid appWindow");
return 0;
}
return xfc->appWindow->handle;
}
else
{
if (!xfc->window)
{
WLog_WARN(TAG, "xf_Pointer: Invalid window");
return 0;
}
return xfc->window->handle;
}
}
static BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer)
{
#ifdef WITH_XCURSOR
UINT32 CursorFormat;
size_t size;
XcursorImage ci;
xfContext* xfc = (xfContext*)context;
xfPointer* xpointer = (xfPointer*)pointer;
@ -244,35 +387,25 @@ static BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer)
else
CursorFormat = (!xfc->big_endian) ? PIXEL_FORMAT_BGRA32 : PIXEL_FORMAT_ARGB32;
xf_lock_x11(xfc);
ZeroMemory(&ci, sizeof(ci));
ci.version = XCURSOR_IMAGE_VERSION;
ci.size = sizeof(ci);
ci.width = pointer->width;
ci.height = pointer->height;
ci.xhot = pointer->xPos;
ci.yhot = pointer->yPos;
size = ci.height * ci.width * GetBytesPerPixel(CursorFormat);
xpointer->nCursors = 0;
xpointer->mCursors = 0;
if (!(ci.pixels = (XcursorPixel*)_aligned_malloc(size, 16)))
{
xf_unlock_x11(xfc);
size = pointer->height * pointer->width * GetBytesPerPixel(CursorFormat);
if (!(xpointer->cursorPixels = (XcursorPixel*)_aligned_malloc(size, 16)))
return FALSE;
}
if (!freerdp_image_copy_from_pointer_data(
(BYTE*)ci.pixels, CursorFormat, 0, 0, 0, pointer->width, pointer->height,
(BYTE*)xpointer->cursorPixels, CursorFormat, 0, 0, 0, pointer->width, pointer->height,
pointer->xorMaskData, pointer->lengthXorMask, pointer->andMaskData,
pointer->lengthAndMask, pointer->xorBpp, &context->gdi->palette))
{
_aligned_free(ci.pixels);
xf_unlock_x11(xfc);
_aligned_free(xpointer->cursorPixels);
return FALSE;
}
xpointer->cursor = XcursorImageLoadCursor(xfc->display, &ci);
_aligned_free(ci.pixels);
xf_unlock_x11(xfc);
if (!_xf_Pointer_GetCursorForCurrentScale(context, pointer, &(xpointer->cursor)))
return FALSE;
#endif
return TRUE;
}
@ -281,10 +414,22 @@ static void xf_Pointer_Free(rdpContext* context, rdpPointer* pointer)
{
#ifdef WITH_XCURSOR
xfContext* xfc = (xfContext*)context;
xfPointer* xpointer = (xfPointer*)pointer;
xf_lock_x11(xfc);
if (((xfPointer*)pointer)->cursor)
XFreeCursor(xfc->display, ((xfPointer*)pointer)->cursor);
_aligned_free(xpointer->cursorPixels);
free(xpointer->cursorWidths);
free(xpointer->cursorHeights);
for (int i = 0; i < xpointer->nCursors; i++)
{
XFreeCursor(xfc->display, xpointer->cursors[i]);
}
free(xpointer->cursors);
xpointer->nCursors = 0;
xpointer->mCursors = 0;
xf_unlock_x11(xfc);
#endif
@ -294,15 +439,19 @@ static BOOL xf_Pointer_Set(rdpContext* context, const rdpPointer* pointer)
{
#ifdef WITH_XCURSOR
xfContext* xfc = (xfContext*)context;
xf_lock_x11(xfc);
Window handle = xf_Pointer_get_window(xfc);
xfc->pointer = (xfPointer*)pointer;
/* in RemoteApp mode, window can be null if none has had focus */
if (xfc->window)
XDefineCursor(xfc->display, xfc->window->handle, xfc->pointer->cursor);
xf_unlock_x11(xfc);
if (handle)
{
if (!_xf_Pointer_GetCursorForCurrentScale(context, pointer, &(xfc->pointer->cursor)))
return FALSE;
xf_lock_x11(xfc);
XDefineCursor(xfc->display, handle, xfc->pointer->cursor);
xf_unlock_x11(xfc);
}
#endif
return TRUE;
}
@ -312,6 +461,7 @@ static BOOL xf_Pointer_SetNull(rdpContext* context)
#ifdef WITH_XCURSOR
xfContext* xfc = (xfContext*)context;
static Cursor nullcursor = None;
Window handle = xf_Pointer_get_window(xfc);
xf_lock_x11(xfc);
if (nullcursor == None)
@ -329,8 +479,8 @@ static BOOL xf_Pointer_SetNull(rdpContext* context)
xfc->pointer = NULL;
if ((xfc->window) && (nullcursor != None))
XDefineCursor(xfc->display, xfc->window->handle, nullcursor);
if ((handle) && (nullcursor != None))
XDefineCursor(xfc->display, handle, nullcursor);
xf_unlock_x11(xfc);
#endif
@ -341,11 +491,12 @@ static BOOL xf_Pointer_SetDefault(rdpContext* context)
{
#ifdef WITH_XCURSOR
xfContext* xfc = (xfContext*)context;
Window handle = xf_Pointer_get_window(xfc);
xf_lock_x11(xfc);
xfc->pointer = NULL;
if (xfc->window)
XUndefineCursor(xfc->display, xfc->window->handle);
if (handle)
XUndefineCursor(xfc->display, handle);
xf_unlock_x11(xfc);
#endif
@ -358,23 +509,43 @@ static BOOL xf_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
XWindowAttributes current;
XSetWindowAttributes tmp;
BOOL ret = FALSE;
Status rc;
Window handle = xf_Pointer_get_window(xfc);
if (!xfc->focused || !xfc->window)
if (!handle)
{
WLog_WARN(TAG, "xf_Pointer_SetPosition: focus %d, handle%lu", xfc->focused, handle);
return TRUE;
}
if (xfc->remote_app && !xfc->focused)
return TRUE;
xf_lock_x11(xfc);
if (XGetWindowAttributes(xfc->display, xfc->window->handle, &current) == 0)
rc = XGetWindowAttributes(xfc->display, handle, &current);
if (rc == 0)
{
WLog_WARN(TAG, "xf_Pointer_SetPosition: XGetWindowAttributes==%d", rc);
goto out;
}
tmp.event_mask = (current.your_event_mask & ~(PointerMotionMask));
if (XChangeWindowAttributes(xfc->display, xfc->window->handle, CWEventMask, &tmp) == 0)
rc = XChangeWindowAttributes(xfc->display, handle, CWEventMask, &tmp);
if (rc == 0)
{
WLog_WARN(TAG, "xf_Pointer_SetPosition: XChangeWindowAttributes==%d", rc);
goto out;
}
XWarpPointer(xfc->display, None, xfc->window->handle, 0, 0, 0, 0, x, y);
rc = XWarpPointer(xfc->display, None, handle, 0, 0, 0, 0, x, y);
if (rc == 0)
WLog_WARN(TAG, "xf_Pointer_SetPosition: XWrapPointer==%d", rc);
tmp.event_mask = current.your_event_mask;
XChangeWindowAttributes(xfc->display, xfc->window->handle, CWEventMask, &tmp);
rc = XChangeWindowAttributes(xfc->display, handle, CWEventMask, &tmp);
if (rc == 0)
WLog_WARN(TAG, "xf_Pointer_SetPosition: 2.try XChangeWindowAttributes==%d", rc);
ret = TRUE;
out:
xf_unlock_x11(xfc);

View File

@ -480,13 +480,19 @@ static int xf_input_handle_event_local(xfContext* xfc, const XEvent* event)
static char* xf_input_touch_state_string(DWORD flags)
{
if (flags & CONTACT_FLAG_DOWN)
return "TouchBegin";
return "RDPINPUT::CONTACT_FLAG_DOWN";
else if (flags & CONTACT_FLAG_UPDATE)
return "TouchUpdate";
return "RDPINPUT::CONTACT_FLAG_UPDATE";
else if (flags & CONTACT_FLAG_UP)
return "TouchEnd";
return "RDPINPUT::CONTACT_FLAG_UP";
else if (flags & CONTACT_FLAG_INRANGE)
return "RDPINPUT::CONTACT_FLAG_INRANGE";
else if (flags & CONTACT_FLAG_INCONTACT)
return "RDPINPUT::CONTACT_FLAG_INCONTACT";
else if (flags & CONTACT_FLAG_CANCELED)
return "RDPINPUT::CONTACT_FLAG_CANCELED";
else
return "TouchUnknown";
return "RDPINPUT::CONTACT_FLAG_UNKNOWN";
}
#endif

View File

@ -43,8 +43,16 @@
#include <freerdp/log.h>
#define TAG CLIENT_TAG("x11")
static BOOL firstPressRightCtrl = TRUE;
static BOOL ungrabKeyboardWithRightCtrl = TRUE;
static BOOL xf_sync_kbd_state(xfContext* xfc)
{
const UINT32 syncFlags = xf_keyboard_get_toggle_keys_state(xfc);
return freerdp_input_send_synchronize_event(xfc->context.input, syncFlags);
}
static void xf_keyboard_clear(xfContext* xfc)
{
ZeroMemory(xfc->KeyboardState, 256 * sizeof(BOOL));
}
static BOOL xf_keyboard_action_script_init(xfContext* xfc)
{
@ -107,7 +115,8 @@ BOOL xf_keyboard_init(xfContext* xfc)
{
xf_keyboard_clear(xfc);
xfc->KeyboardLayout = xfc->context.settings->KeyboardLayout;
xfc->KeyboardLayout = freerdp_keyboard_init(xfc->KeyboardLayout);
xfc->KeyboardLayout =
freerdp_keyboard_init_ex(xfc->KeyboardLayout, xfc->context.settings->KeyboardRemappingList);
xfc->context.settings->KeyboardLayout = xfc->KeyboardLayout;
if (xfc->modifierMap)
@ -131,11 +140,6 @@ void xf_keyboard_free(xfContext* xfc)
xf_keyboard_action_script_free(xfc);
}
void xf_keyboard_clear(xfContext* xfc)
{
ZeroMemory(xfc->KeyboardState, 256 * sizeof(BOOL));
}
void xf_keyboard_key_press(xfContext* xfc, BYTE keycode, KeySym keysym)
{
if (keycode < 8)
@ -179,6 +183,7 @@ void xf_keyboard_release_all_keypress(xfContext* xfc)
xfc->KeyboardState[keycode] = FALSE;
}
}
xf_sync_kbd_state(xfc);
}
BOOL xf_keyboard_key_pressed(xfContext* xfc, KeySym keysym)
@ -216,9 +221,7 @@ void xf_keyboard_send_key(xfContext* xfc, BOOL down, BYTE keycode)
if ((rdp_scancode == RDP_SCANCODE_CAPSLOCK) && (down == FALSE))
{
UINT32 syncFlags;
syncFlags = xf_keyboard_get_toggle_keys_state(xfc);
input->SynchronizeEvent(input, syncFlags);
xf_sync_kbd_state(xfc);
}
}
}
@ -349,7 +352,7 @@ void xf_keyboard_focus_in(xfContext* xfc)
input = xfc->context.input;
syncFlags = xf_keyboard_get_toggle_keys_state(xfc);
input->FocusInEvent(input, syncFlags);
freerdp_input_send_focus_in_event(input, syncFlags);
xk_keyboard_update_modifier_keys(xfc);
/* finish with a mouse pointer position like mstsc.exe if required */
@ -362,7 +365,7 @@ void xf_keyboard_focus_in(xfContext* xfc)
if (x >= 0 && x < xfc->window->width && y >= 0 && y < xfc->window->height)
{
xf_event_adjust_coordinates(xfc, &x, &y);
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
freerdp_input_send_mouse_event(input, PTR_FLAGS_MOVE, x, y);
}
}
}
@ -473,18 +476,18 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym)
// do not return anything such that the key could be used by client if ungrab is not the goal
if (keysym == XK_Control_R)
{
if (mod.RightCtrl && firstPressRightCtrl)
if (mod.RightCtrl && xfc->firstPressRightCtrl)
{
// Right Ctrl is pressed, getting ready to ungrab
ungrabKeyboardWithRightCtrl = TRUE;
firstPressRightCtrl = FALSE;
xfc->ungrabKeyboardWithRightCtrl = TRUE;
xfc->firstPressRightCtrl = FALSE;
}
}
else
{
// some other key has been pressed, abort ungrabbing
if (ungrabKeyboardWithRightCtrl)
ungrabKeyboardWithRightCtrl = FALSE;
if (xfc->ungrabKeyboardWithRightCtrl)
xfc->ungrabKeyboardWithRightCtrl = FALSE;
}
if (!xf_keyboard_execute_action_script(xfc, &mod, keysym))
@ -603,9 +606,9 @@ void xf_keyboard_handle_special_keys_release(xfContext* xfc, KeySym keysym)
if (keysym != XK_Control_R)
return;
firstPressRightCtrl = TRUE;
xfc->firstPressRightCtrl = TRUE;
if (!ungrabKeyboardWithRightCtrl)
if (!xfc->ungrabKeyboardWithRightCtrl)
return;
// all requirements for ungrab are fulfilled, ungrabbing now
@ -624,7 +627,7 @@ void xf_keyboard_handle_special_keys_release(xfContext* xfc, KeySym keysym)
}
// ungrabbed
ungrabKeyboardWithRightCtrl = FALSE;
xfc->ungrabKeyboardWithRightCtrl = FALSE;
}
BOOL xf_keyboard_set_indicators(rdpContext* context, UINT16 led_flags)

View File

@ -44,7 +44,7 @@ typedef struct _XF_MODIFIER_KEYS XF_MODIFIER_KEYS;
BOOL xf_keyboard_init(xfContext* xfc);
void xf_keyboard_free(xfContext* xfc);
void xf_keyboard_clear(xfContext* xfc);
void xf_keyboard_key_press(xfContext* xfc, BYTE keycode, KeySym keysym);
void xf_keyboard_key_release(xfContext* xfc, BYTE keycode, KeySym keysym);
void xf_keyboard_release_all_keypress(xfContext* xfc);

View File

@ -180,7 +180,7 @@ void xf_rail_end_local_move(xfContext* xfc, xfAppWindow* appWindow)
if ((appWindow->local_move.direction != _NET_WM_MOVERESIZE_MOVE_KEYBOARD) &&
(appWindow->local_move.direction != _NET_WM_MOVERESIZE_SIZE_KEYBOARD))
{
input->MouseEvent(input, PTR_FLAGS_BUTTON1, x, y);
freerdp_input_send_mouse_event(input, PTR_FLAGS_BUTTON1, x, y);
}
/*
@ -595,7 +595,7 @@ static xfRailIcon* RailIconCache_Lookup(xfRailIconCache* cache, UINT8 cacheId, U
* in ARGB format (e.g., 0xFFFF0000L is opaque red), pixels are in normal,
* left-to-right top-down order.
*/
static BOOL convert_rail_icon(ICON_INFO* iconInfo, xfRailIcon* railIcon)
static BOOL convert_rail_icon(const ICON_INFO* iconInfo, xfRailIcon* railIcon)
{
BYTE* argbPixels = NULL;
BYTE* nextPixel;

View File

@ -123,11 +123,11 @@ static void xf_SetWindowTitleText(xfContext* xfc, Window window, const char* nam
*/
void xf_SendClientEvent(xfContext* xfc, Window window, Atom atom, unsigned int numArgs, ...)
{
XEvent xevent;
XEvent xevent = { 0 };
unsigned int i;
va_list argp;
va_start(argp, numArgs);
ZeroMemory(&xevent, sizeof(XEvent));
xevent.xclient.type = ClientMessage;
xevent.xclient.serial = 0;
xevent.xclient.send_event = False;
@ -574,6 +574,10 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int heig
}
window->floatbar = xf_floatbar_new(xfc, window->handle, name, settings->Floatbar);
if (xfc->_XWAYLAND_MAY_GRAB_KEYBOARD)
xf_SendClientEvent(xfc, window->handle, xfc->_XWAYLAND_MAY_GRAB_KEYBOARD, 1, 1);
return window;
}
@ -819,6 +823,9 @@ int xf_AppWindowCreate(xfContext* xfc, xfAppWindow* appWindow)
FocusChangeMask | PropertyChangeMask | ColormapChangeMask | OwnerGrabButtonMask;
XSelectInput(xfc->display, appWindow->handle, input_mask);
if (xfc->_XWAYLAND_MAY_GRAB_KEYBOARD)
xf_SendClientEvent(xfc, appWindow->handle, xfc->_XWAYLAND_MAY_GRAB_KEYBOARD, 1, 1);
return 1;
}
@ -1072,6 +1079,9 @@ void xf_DestroyWindow(xfContext* xfc, xfAppWindow* appWindow)
if (!appWindow)
return;
if (xfc->appWindow == appWindow)
xfc->appWindow = NULL;
if (appWindow->gc)
XFreeGC(xfc->display, appWindow->gc);

View File

@ -28,6 +28,10 @@
typedef struct xf_context xfContext;
#ifdef WITH_XCURSOR
#include <X11/Xcursor/Xcursor.h>
#endif
#include <freerdp/api.h>
#include "xf_window.h"
@ -48,6 +52,14 @@ typedef struct xf_context xfContext;
#include <freerdp/codec/progressive.h>
#include <freerdp/codec/region.h>
#if !defined(XcursorUInt)
typedef unsigned int XcursorUInt;
#endif
#if !defined(XcursorPixel)
typedef XcursorUInt XcursorPixel;
#endif
struct xf_FullscreenMonitors
{
UINT32 top;
@ -69,6 +81,12 @@ typedef struct xf_WorkArea xfWorkArea;
struct xf_pointer
{
rdpPointer pointer;
XcursorPixel* cursorPixels;
UINT32 nCursors;
UINT32 mCursors;
UINT32* cursorWidths;
UINT32* cursorHeights;
Cursor* cursors;
Cursor cursor;
};
typedef struct xf_pointer xfPointer;
@ -190,6 +208,8 @@ struct xf_context
Atom UTF8_STRING;
Atom _XWAYLAND_MAY_GRAB_KEYBOARD;
Atom _NET_WM_ICON;
Atom _MOTIF_WM_HINTS;
Atom _NET_CURRENT_DESKTOP;
@ -248,6 +268,8 @@ struct xf_context
button_map button_map[NUM_BUTTONS_MAPPED];
BYTE savedMaximizedState;
UINT32 locked;
BOOL firstPressRightCtrl;
BOOL ungrabKeyboardWithRightCtrl;
};
BOOL xf_create_window(xfContext* xfc);

View File

@ -663,6 +663,66 @@ DWORD client_cli_verify_changed_certificate_ex(freerdp* instance, const char* ho
return client_cli_accept_certificate(instance->settings);
}
BOOL client_cli_present_gateway_message(freerdp* instance, UINT32 type, BOOL isDisplayMandatory,
BOOL isConsentMandatory, size_t length,
const WCHAR* message)
{
char answer;
const char* msgType = (type == GATEWAY_MESSAGE_CONSENT) ? "Consent message" : "Service message";
if (!isDisplayMandatory && !isConsentMandatory)
return TRUE;
printf("%s:\n", msgType);
#if defined(WIN32)
printf("%.*S\n", (int)length, message);
#else
{
LPSTR msg;
if (ConvertFromUnicode(CP_UTF8, 0, message, (int)(length / 2), &msg, 0, NULL, NULL) < 1)
{
printf("Failed to convert message!\n");
return FALSE;
}
printf("%s\n", msg);
free(msg);
}
#endif
while (isConsentMandatory)
{
printf("I understand and agree to the terms of this policy (Y/N) \n");
fflush(stdout);
answer = fgetc(stdin);
if (feof(stdin))
{
printf("\nError: Could not read answer from stdin.\n");
return FALSE;
}
switch (answer)
{
case 'y':
case 'Y':
fgetc(stdin);
return TRUE;
case 'n':
case 'N':
fgetc(stdin);
return FALSE;
default:
break;
}
printf("\n");
}
return TRUE;
}
BOOL client_auto_reconnect(freerdp* instance)
{
return client_auto_reconnect_ex(instance, NULL);
@ -670,6 +730,7 @@ BOOL client_auto_reconnect(freerdp* instance)
BOOL client_auto_reconnect_ex(freerdp* instance, BOOL (*window_events)(freerdp* instance))
{
UINT32 error;
UINT32 maxRetries;
UINT32 numRetries = 0;
rdpSettings* settings;
@ -681,11 +742,21 @@ BOOL client_auto_reconnect_ex(freerdp* instance, BOOL (*window_events)(freerdp*
maxRetries = settings->AutoReconnectMaxRetries;
/* Only auto reconnect on network disconnects. */
if (freerdp_error_info(instance) != 0)
return FALSE;
/* A network disconnect was detected */
WLog_INFO(TAG, "Network disconnect!");
error = freerdp_error_info(instance);
switch (error)
{
case ERRINFO_GRAPHICS_SUBSYSTEM_FAILED:
/* A network disconnect was detected */
WLog_WARN(TAG, "Disconnected by server hitting a bug or resource limit [%s]",
freerdp_get_error_info_string(error));
break;
case ERRINFO_SUCCESS:
/* A network disconnect was detected */
WLog_INFO(TAG, "Network disconnect!");
break;
default:
return FALSE;
}
if (!settings->AutoReconnectionEnabled)
{

View File

@ -1403,14 +1403,14 @@ int freerdp_client_settings_command_line_status_print_ex(rdpSettings* settings,
if (status == COMMAND_LINE_STATUS_PRINT_VERSION)
{
freerdp_client_print_version();
return COMMAND_LINE_STATUS_PRINT_VERSION;
goto out;
}
if (status == COMMAND_LINE_STATUS_PRINT_BUILDCONFIG)
{
freerdp_client_print_version();
freerdp_client_print_buildconfig();
return COMMAND_LINE_STATUS_PRINT_BUILDCONFIG;
goto out;
}
else if (status == COMMAND_LINE_STATUS_PRINT)
{
@ -1465,15 +1465,18 @@ int freerdp_client_settings_command_line_status_print_ex(rdpSettings* settings,
settings->ListMonitors = TRUE;
}
return COMMAND_LINE_STATUS_PRINT;
goto out;
}
else if (status < 0)
{
freerdp_client_print_command_line_help_ex(argc, argv, custom);
return COMMAND_LINE_STATUS_PRINT_HELP;
goto out;
}
return 0;
out:
if (status <= COMMAND_LINE_STATUS_PRINT && status >= COMMAND_LINE_STATUS_PRINT_LAST)
return 0;
return status;
}
static BOOL ends_with(const char* str, const char* ext)
@ -1567,9 +1570,9 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
else
compatibility = freerdp_client_detect_command_line(argc - 1, &argv[1], &flags);
settings->ProxyHostname = NULL;
settings->ProxyUsername = NULL;
settings->ProxyPassword = NULL;
freerdp_settings_set_string(settings, FreeRDP_ProxyHostname, NULL);
freerdp_settings_set_string(settings, FreeRDP_ProxyUsername, NULL);
freerdp_settings_set_string(settings, FreeRDP_ProxyPassword, NULL);
if (compatibility)
{
@ -1989,6 +1992,11 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
settings->KeyboardLayout = (UINT32)val;
}
CommandLineSwitchCase(arg, "kbd-remap")
{
if (!copy_value(arg->Value, &settings->KeyboardRemappingList))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "kbd-lang")
{
LONGLONG val;
@ -2089,7 +2097,8 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
CommandLineSwitchCase(arg, "proxy")
{
/* initial value */
settings->ProxyType = PROXY_TYPE_HTTP;
if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_HTTP))
return COMMAND_LINE_ERROR_MEMORY;
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
{
@ -2104,12 +2113,23 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
*p = '\0';
if (_stricmp("no_proxy", arg->Value) == 0)
settings->ProxyType = PROXY_TYPE_IGNORE;
{
if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType,
PROXY_TYPE_IGNORE))
return COMMAND_LINE_ERROR_MEMORY;
}
if (_stricmp("http", arg->Value) == 0)
settings->ProxyType = PROXY_TYPE_HTTP;
{
if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType,
PROXY_TYPE_HTTP))
return COMMAND_LINE_ERROR_MEMORY;
}
else if (_stricmp("socks5", arg->Value) == 0)
settings->ProxyType = PROXY_TYPE_SOCKS;
{
if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType,
PROXY_TYPE_SOCKS))
return COMMAND_LINE_ERROR_MEMORY;
}
else
{
WLog_ERR(TAG, "Only HTTP and SOCKS5 proxies supported by now");
@ -2142,18 +2162,15 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
*colonPtr = '\0';
settings->ProxyUsername = _strdup(arg->Value);
if (!settings->ProxyUsername)
if (!freerdp_settings_set_string(settings, FreeRDP_ProxyUsername, arg->Value))
{
WLog_ERR(TAG, "unable to allocate proxy username");
return COMMAND_LINE_ERROR_MEMORY;
}
*atPtr = '\0';
settings->ProxyPassword = _strdup(colonPtr + 1);
if (!settings->ProxyPassword)
if (!freerdp_settings_set_string(settings, FreeRDP_ProxyPassword, colonPtr + 1))
{
WLog_ERR(TAG, "unable to allocate proxy password");
return COMMAND_LINE_ERROR_MEMORY;
@ -2172,11 +2189,16 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
length = (size_t)(p - arg->Value);
settings->ProxyPort = (UINT16)val;
settings->ProxyHostname = (char*)malloc(length + 1);
strncpy(settings->ProxyHostname, arg->Value, length);
settings->ProxyHostname[length] = '\0';
if (!freerdp_settings_set_uint16(settings, FreeRDP_ProxyPort, val))
return FALSE;
*p = '\0';
}
p = strchr(arg->Value, '/');
if (p)
*p = '\0';
if (!freerdp_settings_set_string(settings, FreeRDP_ProxyHostname, arg->Value))
return FALSE;
}
else
{
@ -2326,7 +2348,36 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "clipboard")
{
settings->RedirectClipboard = enable;
if (arg->Value == BoolValueTrue || arg->Value == BoolValueFalse)
{
settings->RedirectClipboard = (arg->Value == BoolValueTrue);
}
else
{
int rc = 0;
char** p;
size_t count, x;
p = CommandLineParseCommaSeparatedValues(arg->Value, &count);
for (x = 0; (x < count) && (rc == 0); x++)
{
const char usesel[14] = "use-selection:";
const char* cur = p[x];
if (_strnicmp(usesel, cur, sizeof(usesel)) == 0)
{
const char* val = &cur[sizeof(usesel)];
if (!copy_value(val, &settings->XSelectionAtom))
rc = COMMAND_LINE_ERROR_MEMORY;
settings->RedirectClipboard = TRUE;
}
else
rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
}
free(p);
if (rc)
return rc;
}
}
CommandLineSwitchCase(arg, "shell")
{

View File

@ -63,7 +63,7 @@ static const COMMAND_LINE_ARGUMENT_A args[] = {
{ "auth-only", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL,
"Authenticate only" },
{ "authentication", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
"Authentication (expermiental)" },
"Authentication (experimental)" },
{ "auto-reconnect", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL,
"Automatic reconnection" },
{ "auto-reconnect-max-retries", COMMAND_LINE_VALUE_REQUIRED, "<retries>", NULL, NULL, -1, NULL,
@ -102,8 +102,12 @@ static const COMMAND_LINE_ARGUMENT_A args[] = {
"Client Build Number sent to server (influences smartcard behaviour, see [MS-RDPESC])" },
{ "client-hostname", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL,
"Client Hostname to send to server" },
{ "clipboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
"Redirect clipboard" },
{ "clipboard", COMMAND_LINE_VALUE_BOOL | COMMAND_LINE_VALUE_OPTIONAL, "[use-selection:<atom>]",
BoolValueTrue, NULL, -1, NULL,
"Redirect clipboard. "
" * use-selection:<atom> ... (X11) Specify which X selection to access. Default is "
"CLIPBOARD."
" PRIMARY is the X-style middle-click selection." },
{ "codec-cache", COMMAND_LINE_VALUE_REQUIRED, "[rfx|nsc|jpeg]", NULL, NULL, -1, NULL,
"Bitmap codec cache" },
{ "compression", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, "z", "compression" },
@ -206,6 +210,9 @@ static const COMMAND_LINE_ARGUMENT_A args[] = {
"List keyboard layouts" },
{ "kbd-lang-list", COMMAND_LINE_VALUE_OPTIONAL | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL,
"List keyboard languages" },
{ "kbd-remap", COMMAND_LINE_VALUE_REQUIRED,
"List of <key>=<value>,... pairs to remap scancodes", NULL, NULL, -1, NULL,
"Keyboard scancode remapping" },
{ "kbd-subtype", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL,
"Keyboard subtype" },
{ "kbd-type", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Keyboard type" },

View File

@ -1772,8 +1772,7 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
{
if (!freerdp_settings_set_string(settings, FreeRDP_PreconnectionBlob,
file->PreconnectionBlob) ||
!freerdp_settings_set_bool(settings, FreeRDP_SendPreconnectionPdu, TRUE) ||
!freerdp_settings_set_bool(settings, FreeRDP_VmConnectMode, TRUE))
!freerdp_settings_set_bool(settings, FreeRDP_SendPreconnectionPdu, TRUE))
return FALSE;
}

View File

@ -98,12 +98,16 @@ option(WITH_SERVER_INTERFACE "Build servers as a library with an interface" ON)
option(WITH_DEBUG_ALL "Print all debug messages." OFF)
if(WITH_DEBUG_ALL)
message(WARNING "WITH_DEBUG_ALL=ON, the build will be slow and might leak sensitive information, do not use with release builds!")
set(DEFAULT_DEBUG_OPTION "ON")
else()
set(DEFAULT_DEBUG_OPTION "OFF")
endif()
option(WITH_DEBUG_CERTIFICATE "Print certificate related debug messages." ${DEFAULT_DEBUG_OPTION})
if(WITH_DEBUG_CERTIFICATE)
message(WARNING "WITH_DEBUG_CERTIFICATE=ON, the build might leak sensitive information, do not use with release builds!")
endif()
option(WITH_DEBUG_CAPABILITIES "Print capability negotiation debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_CHANNELS "Print channel manager debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_CLIPRDR "Print clipboard redirection debug messages" ${DEFAULT_DEBUG_OPTION})
@ -111,10 +115,25 @@ option(WITH_DEBUG_RDPGFX "Print RDPGFX debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_DVC "Print dynamic virtual channel debug messages." ${DEFAULT_DEBUG_OPTION})
CMAKE_DEPENDENT_OPTION(WITH_DEBUG_TSMF "Print TSMF virtual channel debug messages." ${DEFAULT_DEBUG_OPTION} "CHANNEL_TSMF" OFF)
option(WITH_DEBUG_KBD "Print keyboard related debug messages." ${DEFAULT_DEBUG_OPTION})
if(WITH_DEBUG_KBD)
message(WARNING "WITH_DEBUG_KBD=ON, the build might leak sensitive information, do not use with release builds!")
endif()
option(WITH_DEBUG_LICENSE "Print license debug messages." ${DEFAULT_DEBUG_OPTION})
if(WITH_DEBUG_LICENSE)
message(WARNING "WITH_DEBUG_LICENSE=ON, the build might leak sensitive information, do not use with release builds!")
endif()
option(WITH_DEBUG_NEGO "Print negotiation related debug messages." ${DEFAULT_DEBUG_OPTION})
if(WITH_DEBUG_NEGO)
message(WARNING "WITH_DEBUG_NEGO=ON, the build might leak sensitive information, do not use with release builds!")
endif()
option(WITH_DEBUG_NLA "Print authentication related debug messages." ${DEFAULT_DEBUG_OPTION})
if(WITH_DEBUG_NLA)
message(WARNING "WITH_DEBUG_NLA=ON, the build might leak sensitive information, do not use with release builds!")
endif()
option(WITH_DEBUG_NTLM "Print NTLM debug messages" ${DEFAULT_DEBUG_OPTION})
if(WITH_DEBUG_NTLM)
message(WARNING "WITH_DEBUG_NTLM=ON, the build might leak sensitive information, do not use with release builds!")
endif()
option(WITH_DEBUG_TSG "Print Terminal Server Gateway debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_RAIL "Print RemoteApp debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_RDP "Print RDP debug messages" ${DEFAULT_DEBUG_OPTION})

View File

@ -19,5 +19,5 @@ if (NOT FREERDP_IOS_EXTERNAL_SSL_PATH)
set(FREERDP_IOS_EXTERNAL_SSL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/external/openssl")
endif()
mark_as_advanced(FREERDP_IOS_EXTERNAL_SSL_PATH)
set(IOS_TARGET_SDK 9.3 CACHE STRING "Application target iOS SDK")
set(IOS_TARGET_SDK 12.0 CACHE STRING "Application target iOS SDK")

View File

@ -187,6 +187,7 @@ typedef BOOL (*pDrawGdiPlusCacheNext)(rdpContext* context,
const DRAW_GDIPLUS_CACHE_NEXT_ORDER* draw_gdiplus_cache_next);
typedef BOOL (*pDrawGdiPlusCacheEnd)(rdpContext* context,
const DRAW_GDIPLUS_CACHE_END_ORDER* draw_gdiplus_cache_end);
typedef BOOL (*pDrawOrderInfo)(rdpContext* context, UINT8 orderType, const char* orderName);
struct rdp_altsec_update
{
@ -205,7 +206,9 @@ struct rdp_altsec_update
pDrawGdiPlusCacheFirst DrawGdiPlusCacheFirst; /* 25 */
pDrawGdiPlusCacheNext DrawGdiPlusCacheNext; /* 26 */
pDrawGdiPlusCacheEnd DrawGdiPlusCacheEnd; /* 27 */
UINT32 paddingB[32 - 28]; /* 28 */
/* Statistics callback */
pDrawOrderInfo DrawOrderInfo; /* 28 */
UINT32 paddingB[32 - 29]; /* 29 */
/* internal */

View File

@ -24,4 +24,6 @@
#include <freerdp/dvc.h>
#include <freerdp/types.h>
#define AUDIN_DVC_CHANNEL_NAME "AUDIO_INPUT"
#endif /* FREERDP_CHANNEL_AUDIN_H */

View File

@ -70,6 +70,7 @@
#define CB_STREAM_FILECLIP_ENABLED 0x00000004
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008
#define CB_CAN_LOCK_CLIPDATA 0x00000010
#define CB_HUGE_FILE_SUPPORT_ENABLED 0x00000020
/* File Contents Request Flags */
#define FILECONTENTS_SIZE 0x00000001
@ -93,11 +94,15 @@ extern "C"
#endif
FREERDP_API UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length,
FILEDESCRIPTOR** file_descriptor_array,
FILEDESCRIPTORW** file_descriptor_array,
UINT32* file_descriptor_count);
FREERDP_API UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array,
FREERDP_API UINT cliprdr_serialize_file_list(const FILEDESCRIPTORW* file_descriptor_array,
UINT32 file_descriptor_count, BYTE** format_data,
UINT32* format_data_length);
FREERDP_API UINT cliprdr_serialize_file_list_ex(UINT32 flags,
const FILEDESCRIPTORW* file_descriptor_array,
UINT32 file_descriptor_count,
BYTE** format_data, UINT32* format_data_length);
#ifdef __cplusplus
}

View File

@ -0,0 +1,30 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Audio Input Redirection Virtual Channel
*
* Copyright 2020 Armin Novak <anovak@thincast.com>
* Copyright 2020 Thincast Technologies GmbH
*
* 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_ECHO_H
#define FREERDP_CHANNEL_ECHO_H
#include <freerdp/api.h>
#include <freerdp/dvc.h>
#include <freerdp/types.h>
#define ECHO_DVC_CHANNEL_NAME "ECHO"
#endif /* FREERDP_CHANNEL_ECHO_H */

View File

@ -32,23 +32,48 @@
enum
{
RDPINPUT_PROTOCOL_V10 = 0x00010000,
RDPINPUT_PROTOCOL_V101 = 0x00010001
RDPINPUT_PROTOCOL_V101 = 0x00010001,
RDPINPUT_PROTOCOL_V200 = 0x00020000,
RDPINPUT_PROTOCOL_V300 = 0x00030000
};
/* Client Ready Flags */
#define READY_FLAGS_SHOW_TOUCH_VISUALS 0x00000001
#define READY_FLAGS_DISABLE_TIMESTAMP_INJECTION 0x00000002
#define READY_FLAGS_SHOW_TOUCH_VISUALS 0x00000001 /* Deprecated */
#define READY_FLAGS_DISABLE_TIMESTAMP_INJECTION 0x00000002 /* Deprecated */
#define CS_READY_FLAGS_SHOW_TOUCH_VISUALS 0x00000001
#define CS_READY_FLAGS_DISABLE_TIMESTAMP_INJECTION 0x00000002
#define CS_READY_FLAGS_ENABLE_MULTIPEN_INJECTION 0x00000004
#define CONTACT_DATA_CONTACTRECT_PRESENT 0x0001
#define CONTACT_DATA_ORIENTATION_PRESENT 0x0002
#define CONTACT_DATA_PRESSURE_PRESENT 0x0004
#define CONTACT_FLAG_DOWN 0x0001
#define CONTACT_FLAG_UPDATE 0x0002
#define CONTACT_FLAG_UP 0x0004
#define CONTACT_FLAG_INRANGE 0x0008
#define CONTACT_FLAG_INCONTACT 0x0010
#define CONTACT_FLAG_CANCELED 0x0020
typedef enum
{
PEN_CONTACT_PENFLAGS_PRESENT = 0x0001,
PEN_CONTACT_PRESSURE_PRESENT = 0x0002,
PEN_CONTACT_ROTATION_PRESENT = 0x0004,
PEN_CONTACT_TILTX_PRESENT = 0x0008,
PEN_CONTACT_TILTY_PRESENT = 0x0010
} RDPINPUT_PEN_FIELDS_PRESENT;
typedef enum
{
CONTACT_FLAG_DOWN = 0x0001,
CONTACT_FLAG_UPDATE = 0x0002,
CONTACT_FLAG_UP = 0x0004,
CONTACT_FLAG_INRANGE = 0x0008,
CONTACT_FLAG_INCONTACT = 0x0010,
CONTACT_FLAG_CANCELED = 0x0020
} RDPINPUT_CONTACT_FLAGS;
typedef enum
{
PEN_FLAG_BARREL_PRESSED = 0x0001,
PEN_FLAG_ERASER_PRESSED = 0x0002,
PEN_FLAG_INVERTED = 0x0004
} RDPINPUT_PEN_FLAGS;
/** @brief a contact point */
struct _RDPINPUT_CONTACT_DATA
@ -85,4 +110,35 @@ struct _RDPINPUT_TOUCH_EVENT
};
typedef struct _RDPINPUT_TOUCH_EVENT RDPINPUT_TOUCH_EVENT;
struct _RDPINPUT_PEN_CONTACT
{
UINT8 deviceId;
UINT16 fieldsPresent;
INT32 x;
INT32 y;
UINT32 contactFlags;
UINT32 penFlags;
UINT32 pressure;
UINT16 rotation;
INT16 tiltX;
INT16 tiltY;
};
typedef struct _RDPINPUT_PEN_CONTACT RDPINPUT_PEN_CONTACT;
struct _RDPINPUT_PEN_FRAME
{
UINT16 contactCount;
UINT64 frameOffset;
RDPINPUT_PEN_CONTACT* contacts;
};
typedef struct _RDPINPUT_PEN_FRAME RDPINPUT_PEN_FRAME;
/** @brief a touch event with some frames*/
struct _RDPINPUT_PEN_EVENT
{
UINT32 encodeTime;
UINT16 frameCount;
RDPINPUT_PEN_FRAME* frames;
};
typedef struct _RDPINPUT_PEN_EVENT RDPINPUT_PEN_EVENT;
#endif /* FREERDP_CHANNEL_RDPEI_H */

View File

@ -123,6 +123,12 @@ extern "C"
freerdp* instance, const char* host, UINT16 port, const char* common_name,
const char* subject, const char* issuer, const char* fingerprint, const char* old_subject,
const char* old_issuer, const char* old_fingerprint, DWORD flags);
FREERDP_API BOOL client_cli_present_gateway_message(freerdp* instance, UINT32 type,
BOOL isDisplayMandatory,
BOOL isConsentMandatory, size_t length,
const WCHAR* message);
FREERDP_API BOOL client_auto_reconnect(freerdp* instance);
FREERDP_API BOOL client_auto_reconnect_ex(freerdp* instance,
BOOL (*window_events)(freerdp* instance));

View File

@ -30,16 +30,23 @@
typedef struct _rdpei_client_context RdpeiClientContext;
typedef int (*pcRdpeiGetVersion)(RdpeiClientContext* context);
typedef UINT32 (*pcRdpeiGetVersion)(RdpeiClientContext* context);
typedef UINT32 (*pcRdpeiGetFeatures)(RdpeiClientContext* context);
typedef UINT (*pcRdpeiAddContact)(RdpeiClientContext* context,
const RDPINPUT_CONTACT_DATA* contact);
typedef UINT (*pcRdpeiTouchBegin)(RdpeiClientContext* context, int externalId, int x, int y,
int* contactId);
typedef UINT (*pcRdpeiTouchUpdate)(RdpeiClientContext* context, int externalId, int x, int y,
int* contactId);
typedef UINT (*pcRdpeiTouchEnd)(RdpeiClientContext* context, int externalId, int x, int y,
int* contactId);
typedef UINT (*pcRdpeiTouchBegin)(RdpeiClientContext* context, INT32 externalId, INT32 x, INT32 y,
INT32* contactId);
typedef UINT (*pcRdpeiTouchUpdate)(RdpeiClientContext* context, INT32 externalId, INT32 x, INT32 y,
INT32* contactId);
typedef UINT (*pcRdpeiTouchEnd)(RdpeiClientContext* context, INT32 externalId, INT32 x, INT32 y,
INT32* contactId);
typedef UINT (*pcRdpeiAddPen)(RdpeiClientContext* context, INT32 externalId,
const RDPINPUT_PEN_CONTACT* contact);
typedef UINT (*pcRdpeiPen)(RdpeiClientContext* context, INT32 externalId, UINT32 fieldFlags,
INT32 x, INT32 y, ...);
typedef UINT (*pcRdpeiSuspendTouch)(RdpeiClientContext* context);
typedef UINT (*pcRdpeiResumeTouch)(RdpeiClientContext* context);
@ -59,6 +66,13 @@ struct _rdpei_client_context
pcRdpeiSuspendTouch SuspendTouch;
pcRdpeiResumeTouch ResumeTouch;
pcRdpeiGetFeatures GetFeatures;
pcRdpeiAddPen AddPen;
pcRdpeiPen PenBegin;
pcRdpeiPen PenUpdate;
pcRdpeiPen PenEnd;
};
#endif /* FREERDP_CHANNEL_RDPEI_CLIENT_RDPEI_H */

View File

@ -809,6 +809,27 @@ extern "C"
return TRUE;
}
static INLINE BOOL WriteColorIgnoreAlpha(BYTE* dst, UINT32 format, UINT32 color)
{
switch (format)
{
case PIXEL_FORMAT_ABGR32:
case PIXEL_FORMAT_ARGB32:
{
const UINT32 tmp = (dst[0] << 24) | (color & 0x00FFFFFF);
return WriteColor(dst, format, tmp);
}
case PIXEL_FORMAT_BGRA32:
case PIXEL_FORMAT_RGBA32:
{
const UINT32 tmp = (dst[3]) | (color & 0xFFFFFF00);
return WriteColor(dst, format, tmp);
}
default:
return WriteColor(dst, format, color);
}
}
/***
*
* Converts a pixel in internal representation format srcFormat to internal

View File

@ -97,6 +97,8 @@ struct _BITMAP_PLANAR_CONTEXT
BYTE* pTempData;
UINT32 nTempStep;
BOOL bgr;
};
#ifdef __cplusplus
@ -116,6 +118,8 @@ extern "C"
UINT32 height);
FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context);
FREERDP_API void freerdp_planar_switch_bgr(BITMAP_PLANAR_CONTEXT* planar, BOOL bgr);
FREERDP_API BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData,
UINT32 SrcSize, UINT32 nSrcWidth, UINT32 nSrcHeight,
BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,

View File

@ -37,13 +37,26 @@ extern "C"
{
#endif
FREERDP_API int progressive_compress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize);
FREERDP_API WINPR_DEPRECATED(int progressive_compress(PROGRESSIVE_CONTEXT* progressive,
const BYTE* pSrcData, UINT32 SrcSize,
BYTE** ppDstData, UINT32* pDstSize));
FREERDP_API INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
UINT32 SrcSize, BYTE* pDstData, UINT32 DstFormat,
UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
REGION16* invalidRegion, UINT16 surfaceId);
FREERDP_API int progressive_compress_ex(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
UINT32 SrcSize, UINT32 SrcFormat, UINT32 Width,
UINT32 Height, UINT32 ScanLine,
const REGION16* invalidRegion, BYTE** ppDstData,
UINT32* pDstSize);
FREERDP_API WINPR_DEPRECATED(INT32 progressive_decompress(
PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData,
UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, REGION16* invalidRegion,
UINT16 surfaceId));
FREERDP_API INT32 progressive_decompress_ex(PROGRESSIVE_CONTEXT* progressive,
const BYTE* pSrcData, UINT32 SrcSize,
BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
UINT32 nXDst, UINT32 nYDst, REGION16* invalidRegion,
UINT16 surfaceId, UINT32 frameId);
FREERDP_API INT32 progressive_create_surface_context(PROGRESSIVE_CONTEXT* progressive,
UINT16 surfaceId, UINT32 width,

View File

@ -183,16 +183,23 @@ extern "C"
FREERDP_API void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message);
FREERDP_API BOOL rfx_compose_message(RFX_CONTEXT* context, wStream* s, const RFX_RECT* rects,
int num_rects, BYTE* image_data, int width, int height,
int rowstride);
size_t num_rects, const BYTE* image_data, UINT32 width,
UINT32 height, UINT32 rowstride);
FREERDP_API RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects,
int numRects, BYTE* data, int width, int height,
int scanline);
FREERDP_API RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects,
int numRects, BYTE* data, int width, int height,
int scanline, int* numMessages, int maxDataSize);
FREERDP_API BOOL rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message);
size_t numRects, const BYTE* data, UINT32 width,
UINT32 height, size_t scanline);
FREERDP_API WINPR_DEPRECATED(RFX_MESSAGE* rfx_encode_messages(
RFX_CONTEXT* context, const RFX_RECT* rects, int numRects, const BYTE* data, int width,
int height, int scanline, int* numMessages, int maxDataSize));
FREERDP_API RFX_MESSAGE* rfx_encode_messages_ex(RFX_CONTEXT* context, const RFX_RECT* rects,
size_t numRects, const BYTE* data, UINT32 width,
UINT32 height, UINT32 scanline,
size_t* numMessages, size_t maxDataSize);
FREERDP_API BOOL rfx_write_message(RFX_CONTEXT* context, wStream* s,
const RFX_MESSAGE* message);
FREERDP_API BOOL rfx_context_reset(RFX_CONTEXT* context, UINT32 width, UINT32 height);

View File

@ -177,30 +177,6 @@ extern "C"
FREERDP_API const char* freerdp_get_error_info_name(UINT32 code);
FREERDP_API const char* freerdp_get_error_info_category(UINT32 code);
/**
* This static variable holds an error code if the return value from connect is FALSE.
* This variable is always set to 0 in the beginning of the connect sequence.
* The returned code can be used to inform the user of the detailed connect error.
* The value can hold one of the defined error codes below OR an error according to errno
*/
FREERDP_API extern int connectErrorCode;
#define ERRORSTART 10000
#define PREECONNECTERROR ERRORSTART + 1
#define UNDEFINEDCONNECTERROR ERRORSTART + 2
#define POSTCONNECTERROR ERRORSTART + 3
#define DNSERROR ERRORSTART + 4 /* general DNS ERROR */
#define DNSNAMENOTFOUND ERRORSTART + 5 /* EAI_NONAME */
#define CONNECTERROR \
ERRORSTART + 6 /* a connect error if errno is not define during tcp connect \
*/
#define MCSCONNECTINITIALERROR ERRORSTART + 7
#define TLSCONNECTERROR ERRORSTART + 8
#define AUTHENTICATIONERROR ERRORSTART + 9
#define INSUFFICIENTPRIVILEGESERROR ERRORSTART + 10
#define CANCELEDBYUSER ERRORSTART + 11
/**
* FreeRDP Context Error Codes
*/

View File

@ -71,6 +71,11 @@ extern "C"
BOOL firstActivation;
DEFINE_EVENT_END(Activated)
DEFINE_EVENT_BEGIN(ConnectionStateChange)
int state;
BOOL active;
DEFINE_EVENT_END(ConnectionStateChange)
DEFINE_EVENT_BEGIN(Terminate)
int code;
DEFINE_EVENT_END(Terminate)

View File

@ -70,6 +70,10 @@ extern "C"
#define VERIFY_CERT_FLAG_MISMATCH 0x80
#define VERIFY_CERT_FLAG_MATCH_LEGACY_SHA1 0x100
/* Message types used by gateway messaging callback */
#define GATEWAY_MESSAGE_CONSENT 1
#define GATEWAY_MESSAGE_SERVICE 2
typedef BOOL (*pContextNew)(freerdp* instance, rdpContext* context);
typedef void (*pContextFree)(freerdp* instance, rdpContext* context);
@ -183,6 +187,7 @@ extern "C"
typedef BOOL (*pReceiveChannelData)(freerdp* instance, UINT16 channelId, const BYTE* data,
size_t size, UINT32 flags, size_t totalSize);
/* type can be one of the GATEWAY_MESSAGE_ type defines */
typedef BOOL (*pPresentGatewayMessage)(freerdp* instance, UINT32 type, BOOL isDisplayMandatory,
BOOL isConsentMandatory, size_t length,
const WCHAR* message);

View File

@ -525,6 +525,7 @@ struct rdp_gdi
GeometryClientContext* geometry;
wLog* log;
UINT32 frameId;
};
#ifdef __cplusplus

View File

@ -220,6 +220,8 @@ extern "C"
#endif
FREERDP_API DWORD freerdp_keyboard_init(DWORD keyboardLayoutId);
FREERDP_API DWORD freerdp_keyboard_init_ex(DWORD keyboardLayoutId,
const char* keyboardRemappingList);
FREERDP_API RDP_KEYBOARD_LAYOUT* freerdp_keyboard_get_layouts(DWORD types);
FREERDP_API void freerdp_keyboard_layouts_free(RDP_KEYBOARD_LAYOUT* layouts);
FREERDP_API const char* freerdp_keyboard_get_layout_name_from_id(DWORD keyboardLayoutId);

View File

@ -462,6 +462,8 @@ typedef BOOL (*pPolygonSC)(rdpContext* context, const POLYGON_SC_ORDER* polygon_
typedef BOOL (*pPolygonCB)(rdpContext* context, POLYGON_CB_ORDER* polygon_cb);
typedef BOOL (*pEllipseSC)(rdpContext* context, const ELLIPSE_SC_ORDER* ellipse_sc);
typedef BOOL (*pEllipseCB)(rdpContext* context, const ELLIPSE_CB_ORDER* ellipse_cb);
typedef BOOL (*pOrderInfo)(rdpContext* context, const ORDER_INFO* order_info,
const char* order_name);
struct rdp_primary_update
{
@ -490,7 +492,9 @@ struct rdp_primary_update
pPolygonCB PolygonCB; /* 35 */
pEllipseSC EllipseSC; /* 36 */
pEllipseCB EllipseCB; /* 37 */
UINT32 paddingB[48 - 38]; /* 38 */
/* Statistics callback */
pOrderInfo OrderInfo; /* 38 */
UINT32 paddingB[48 - 39]; /* 39 */
/* internal */

View File

@ -172,6 +172,8 @@ typedef BOOL (*pCacheGlyph)(rdpContext* context, const CACHE_GLYPH_ORDER* cache_
typedef BOOL (*pCacheGlyphV2)(rdpContext* context,
const CACHE_GLYPH_V2_ORDER* cache_glyph_v2_order);
typedef BOOL (*pCacheBrush)(rdpContext* context, const CACHE_BRUSH_ORDER* cache_brush_order);
typedef BOOL (*pCacheOrderInfo)(rdpContext* context, UINT16 orderLength, UINT16 extraFlags,
UINT8 orderType, const char* orderName);
struct rdp_secondary_update
{
@ -185,7 +187,9 @@ struct rdp_secondary_update
pCacheGlyph CacheGlyph; /* 20 */
pCacheGlyphV2 CacheGlyphV2; /* 21 */
pCacheBrush CacheBrush; /* 22 */
UINT32 paddingE[32 - 23]; /* 23 */
/* Statistics callback */
pCacheOrderInfo CacheOrderInfo; /* 23 */
UINT32 paddingE[32 - 24]; /* 24 */
/* internal */

View File

@ -126,6 +126,7 @@ struct _cliprdr_server_context
rdpContext* rdpcontext;
BOOL autoInitializationSequence;
UINT32 lastRequestedFormatId;
BOOL hasHugeFileSupport;
};
#ifdef __cplusplus

View File

@ -41,10 +41,12 @@ struct _rdpei_server_context
/** callbacks that can be set by the user */
UINT (*onClientReady)(RdpeiServerContext* context);
UINT (*onTouchEvent)(RdpeiServerContext* context, RDPINPUT_TOUCH_EVENT* touchEvent);
UINT (*onTouchEvent)(RdpeiServerContext* context, const RDPINPUT_TOUCH_EVENT* touchEvent);
UINT (*onTouchReleased)(RdpeiServerContext* context, BYTE contactId);
void* user_data; /* user data, useful for callbacks */
UINT (*onPenEvent)(RdpeiServerContext* context, const RDPINPUT_PEN_EVENT* penEvent);
};
#ifdef __cplusplus
@ -59,7 +61,11 @@ extern "C"
FREERDP_API UINT rdpei_server_init(RdpeiServerContext* context);
FREERDP_API UINT rdpei_server_handle_messages(RdpeiServerContext* context);
FREERDP_API UINT rdpei_server_send_sc_ready(RdpeiServerContext* context, UINT32 version);
FREERDP_API WINPR_DEPRECATED(UINT rdpei_server_send_sc_ready(RdpeiServerContext* context,
UINT32 version));
FREERDP_API UINT rdpei_server_send_sc_ready_ex(RdpeiServerContext* context, UINT32 version,
UINT32 features);
FREERDP_API UINT rdpei_server_suspend(RdpeiServerContext* context);
FREERDP_API UINT rdpei_server_resume(RdpeiServerContext* context);

View File

@ -120,7 +120,8 @@ typedef enum
#define RNS_UD_CS_STRONG_ASYMMETRIC_KEYS 0x0008
#define RNS_UD_CS_VALID_CONNECTION_TYPE 0x0020
#define RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU 0x0040
#define RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT 0x0080
#define RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT 0x0080 /* DEPRECATED: Compatibility define */
#define RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT 0x0080
#define RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL 0x0100
#define RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE 0x0200
#define RNS_UD_CS_SUPPORT_HEARTBEAT_PDU 0x0400
@ -189,14 +190,14 @@ typedef enum
#define NEG_MEMBLT_INDEX 0x03
#define NEG_MEM3BLT_INDEX 0x04
#define NEG_ATEXTOUT_INDEX 0x05
#define NEG_AEXTTEXTOUT_INDEX 0x06 /* Must be ignored */
#define NEG_AEXTTEXTOUT_INDEX 0x06 /* Must be ignored */
#define NEG_DRAWNINEGRID_INDEX 0x07 /* Must be ignored */
#define NEG_LINETO_INDEX 0x08
#define NEG_MULTI_DRAWNINEGRID_INDEX 0x09
#define NEG_OPAQUE_RECT_INDEX 0x0A /* Must be ignored */
#define NEG_SAVEBITMAP_INDEX 0x0B
#define NEG_WTEXTOUT_INDEX 0x0C /* Must be ignored */
#define NEG_MEMBLT_V2_INDEX 0x0D /* Must be ignored */
#define NEG_WTEXTOUT_INDEX 0x0C /* Must be ignored */
#define NEG_MEMBLT_V2_INDEX 0x0D /* Must be ignored */
#define NEG_MEM3BLT_V2_INDEX 0x0E /* Must be ignored */
#define NEG_MULTIDSTBLT_INDEX 0x0F
#define NEG_MULTIPATBLT_INDEX 0x10
@ -799,6 +800,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_BitmapCacheV2CellInfo (2502)
#define FreeRDP_ColorPointerFlag (2560)
#define FreeRDP_PointerCacheSize (2561)
#define FreeRDP_KeyboardRemappingList (2622)
#define FreeRDP_KeyboardCodePage (2623)
#define FreeRDP_KeyboardLayout (2624)
#define FreeRDP_KeyboardType (2625)
@ -1150,22 +1152,22 @@ struct rdp_settings
UINT64 padding1408[1408 - 1346]; /* 1346 */
/* Server Certificate */
ALIGN64 BOOL IgnoreCertificate; /* 1408 */
ALIGN64 char* CertificateName; /* 1409 */
ALIGN64 char* CertificateFile; /* 1410 */
ALIGN64 char* PrivateKeyFile; /* 1411 */
ALIGN64 char* RdpKeyFile; /* 1412 */
ALIGN64 rdpRsaKey* RdpServerRsaKey; /* 1413 */
ALIGN64 rdpCertificate* RdpServerCertificate; /* 1414 */
ALIGN64 BOOL ExternalCertificateManagement; /* 1415 */
ALIGN64 char* CertificateContent; /* 1416 */
ALIGN64 char* PrivateKeyContent; /* 1417 */
ALIGN64 char* RdpKeyContent; /* 1418 */
ALIGN64 BOOL AutoAcceptCertificate; /* 1419 */
ALIGN64 BOOL AutoDenyCertificate; /* 1420 */
ALIGN64 BOOL IgnoreCertificate; /* 1408 */
ALIGN64 char* CertificateName; /* 1409 */
ALIGN64 char* CertificateFile; /* 1410 */
ALIGN64 char* PrivateKeyFile; /* 1411 */
ALIGN64 char* RdpKeyFile; /* 1412 */
ALIGN64 rdpRsaKey* RdpServerRsaKey; /* 1413 */
ALIGN64 rdpCertificate* RdpServerCertificate; /* 1414 */
ALIGN64 BOOL ExternalCertificateManagement; /* 1415 */
ALIGN64 char* CertificateContent; /* 1416 */
ALIGN64 char* PrivateKeyContent; /* 1417 */
ALIGN64 char* RdpKeyContent; /* 1418 */
ALIGN64 BOOL AutoAcceptCertificate; /* 1419 */
ALIGN64 BOOL AutoDenyCertificate; /* 1420 */
ALIGN64 char* CertificateAcceptedFingerprints; /* 1421 */
UINT64 padding1472[1472 - 1422]; /* 1422 */
UINT64 padding1536[1536 - 1472]; /* 1472 */
UINT64 padding1536[1536 - 1472]; /* 1472 */
/**
* User Interface
@ -1332,9 +1334,10 @@ struct rdp_settings
/* Pointer Capabilities */
ALIGN64 BOOL ColorPointerFlag; /* 2560 */
ALIGN64 UINT32 PointerCacheSize; /* 2561 */
UINT64 padding2624[2623 - 2562]; /* 2562 */
UINT64 padding2624[2622 - 2562]; /* 2562 */
/* Input Capabilities */
ALIGN64 char* KeyboardRemappingList; /* 2622 */
ALIGN64 UINT32 KeyboardCodePage; /* 2623 */
ALIGN64 UINT32 KeyboardLayout; /* 2624 */
ALIGN64 UINT32 KeyboardType; /* 2625 */
@ -1559,6 +1562,7 @@ struct rdp_settings
default value - currently UNUSED! */
ALIGN64 char* ActionScript;
ALIGN64 DWORD Floatbar;
ALIGN64 char* XSelectionAtom;
};
typedef struct rdp_settings rdpSettings;

View File

@ -49,7 +49,11 @@ typedef struct _pcap_record pcap_record;
struct _pcap_record
{
pcap_record_header header;
void* data;
union
{
void* data;
const void* cdata;
};
UINT32 length;
pcap_record* next;
};
@ -76,7 +80,7 @@ extern "C"
FREERDP_API rdpPcap* pcap_open(char* name, BOOL write);
FREERDP_API void pcap_close(rdpPcap* pcap);
FREERDP_API BOOL pcap_add_record(rdpPcap* pcap, void* data, UINT32 length);
FREERDP_API BOOL pcap_add_record(rdpPcap* pcap, const void* data, UINT32 length);
FREERDP_API BOOL pcap_has_next_record(rdpPcap* pcap);
FREERDP_API BOOL pcap_get_next_record(rdpPcap* pcap, pcap_record* record);
FREERDP_API BOOL pcap_get_next_record_header(rdpPcap* pcap, pcap_record* record);

View File

@ -241,6 +241,10 @@ BOOL freerdp_image_copy_from_icon_data(BYTE* pDstData, UINT32 DstFormat, UINT32
return FALSE;
}
/* Ensure we have enough source data bytes for image copy. */
if (cbBitsColor < nWidth * nHeight * GetBytesPerPixel(format))
return FALSE;
fill_gdi_palette_for_icon(colorTable, cbColorTable, &palette);
if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, bitsColor,
format, 0, 0, 0, &palette, FREERDP_FLIP_VERTICAL))
@ -576,6 +580,8 @@ static INLINE BOOL overlapping(const BYTE* pDstData, UINT32 nXDst, UINT32 nYDst,
const BYTE* pSrcStart = &pSrcData[nXSrc * srcBytesPerPixel + nYSrc * nSrcStep];
const BYTE* pSrcEnd = pSrcStart + nHeight * nSrcStep;
WINPR_UNUSED(nWidth);
if ((pDstStart >= pSrcStart) && (pDstStart <= pSrcEnd))
return TRUE;
@ -771,8 +777,17 @@ BOOL freerdp_image_scale(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT3
UINT32 nSrcWidth, UINT32 nSrcHeight)
{
BOOL rc = FALSE;
if (nDstStep == 0)
nDstStep = nDstWidth * GetBytesPerPixel(DstFormat);
if (nSrcStep == 0)
nSrcStep = nSrcWidth * GetBytesPerPixel(SrcFormat);
#if defined(SWSCALE_FOUND) || defined(CAIRO_FOUND)
const BYTE* src = &pSrcData[nXSrc * GetBytesPerPixel(SrcFormat) + nYSrc * nSrcStep];
BYTE* dst = &pDstData[nXDst * GetBytesPerPixel(DstFormat) + nYDst * nDstStep];
#endif
/* direct copy is much faster than scaling, so check if we can simply copy... */
if ((nDstWidth == nSrcWidth) && (nDstHeight == nSrcHeight))

View File

@ -33,6 +33,69 @@
#define TAG FREERDP_TAG("codec")
static INLINE UINT32 planar_invert_format(BITMAP_PLANAR_CONTEXT* planar, BOOL alpha,
UINT32 DstFormat)
{
if (planar->bgr && alpha)
{
switch (DstFormat)
{
case PIXEL_FORMAT_ARGB32:
DstFormat = PIXEL_FORMAT_ABGR32;
break;
case PIXEL_FORMAT_XRGB32:
DstFormat = PIXEL_FORMAT_XBGR32;
break;
case PIXEL_FORMAT_ABGR32:
DstFormat = PIXEL_FORMAT_ARGB32;
break;
case PIXEL_FORMAT_XBGR32:
DstFormat = PIXEL_FORMAT_XRGB32;
break;
case PIXEL_FORMAT_BGRA32:
DstFormat = PIXEL_FORMAT_RGBA32;
break;
case PIXEL_FORMAT_BGRX32:
DstFormat = PIXEL_FORMAT_RGBX32;
break;
case PIXEL_FORMAT_RGBA32:
DstFormat = PIXEL_FORMAT_BGRA32;
break;
case PIXEL_FORMAT_RGBX32:
DstFormat = PIXEL_FORMAT_BGRX32;
break;
case PIXEL_FORMAT_RGB24:
DstFormat = PIXEL_FORMAT_BGR24;
break;
case PIXEL_FORMAT_BGR24:
DstFormat = PIXEL_FORMAT_RGB24;
break;
case PIXEL_FORMAT_RGB16:
DstFormat = PIXEL_FORMAT_BGR16;
break;
case PIXEL_FORMAT_BGR16:
DstFormat = PIXEL_FORMAT_RGB16;
break;
case PIXEL_FORMAT_ARGB15:
DstFormat = PIXEL_FORMAT_ABGR15;
break;
case PIXEL_FORMAT_RGB15:
DstFormat = PIXEL_FORMAT_BGR15;
break;
case PIXEL_FORMAT_ABGR15:
DstFormat = PIXEL_FORMAT_ARGB15;
break;
case PIXEL_FORMAT_BGR15:
DstFormat = PIXEL_FORMAT_RGB15;
break;
default:
break;
}
}
return DstFormat;
}
static INLINE BOOL freerdp_bitmap_planar_compress_plane_rle(const BYTE* plane, UINT32 width,
UINT32 height, BYTE* outPlane,
UINT32* dstSize);
@ -391,52 +454,54 @@ static INLINE BOOL writeLine(BYTE** ppRgba, UINT32 DstFormat, UINT32 width, cons
switch (DstFormat)
{
case PIXEL_FORMAT_BGRA32:
for (x = 0; x < width; x++)
{
*(*ppRgba)++ = *(*ppB)++;
*(*ppRgba)++ = *(*ppG)++;
*(*ppRgba)++ = *(*ppR)++;
*(*ppRgba)++ = *(*ppA)++;
}
return TRUE;
case PIXEL_FORMAT_BGRX32:
for (x = 0; x < width; x++)
{
*(*ppRgba)++ = *(*ppB)++;
*(*ppRgba)++ = *(*ppG)++;
*(*ppRgba)++ = *(*ppR)++;
*(*ppRgba)++ = 0xFF;
}
return TRUE;
default:
if (ppA)
{
case PIXEL_FORMAT_BGRA32:
for (x = 0; x < width; x++)
{
BYTE alpha = *(*ppA)++;
UINT32 color = FreeRDPGetColor(DstFormat, *(*ppR)++, *(*ppG)++, *(*ppB)++, alpha);
WriteColor(*ppRgba, DstFormat, color);
*ppRgba += GetBytesPerPixel(DstFormat);
*(*ppRgba)++ = *(*ppB)++;
*(*ppRgba)++ = *(*ppG)++;
*(*ppRgba)++ = *(*ppR)++;
*(*ppRgba)++ = *(*ppA)++;
}
}
else
{
const BYTE alpha = 0xFF;
return TRUE;
case PIXEL_FORMAT_BGRX32:
for (x = 0; x < width; x++)
{
UINT32 color = FreeRDPGetColor(DstFormat, *(*ppR)++, *(*ppG)++, *(*ppB)++, alpha);
WriteColor(*ppRgba, DstFormat, color);
*ppRgba += GetBytesPerPixel(DstFormat);
*(*ppRgba)++ = *(*ppB)++;
*(*ppRgba)++ = *(*ppG)++;
*(*ppRgba)++ = *(*ppR)++;
*(*ppRgba)++ = 0xFF;
}
}
return TRUE;
return TRUE;
default:
if (ppA)
{
for (x = 0; x < width; x++)
{
BYTE alpha = *(*ppA)++;
UINT32 color =
FreeRDPGetColor(DstFormat, *(*ppR)++, *(*ppG)++, *(*ppB)++, alpha);
WriteColor(*ppRgba, DstFormat, color);
*ppRgba += GetBytesPerPixel(DstFormat);
}
}
else
{
const BYTE alpha = 0xFF;
for (x = 0; x < width; x++)
{
UINT32 color =
FreeRDPGetColor(DstFormat, *(*ppR)++, *(*ppG)++, *(*ppB)++, alpha);
WriteColor(*ppRgba, DstFormat, color);
*ppRgba += GetBytesPerPixel(DstFormat);
}
}
return TRUE;
}
}
@ -482,6 +547,8 @@ static BOOL planar_subsample_expand(const BYTE* plane, size_t planeLength, UINT3
{
size_t pos = 0;
UINT32 y;
WINPR_UNUSED(planeLength);
if (!plane || !deltaPlane)
return FALSE;
@ -548,6 +615,8 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
rle = (FormatHeader & PLANAR_FORMAT_HEADER_RLE) ? TRUE : FALSE;
alpha = (FormatHeader & PLANAR_FORMAT_HEADER_NA) ? FALSE : TRUE;
DstFormat = planar_invert_format(planar, alpha, DstFormat);
if (alpha)
useAlpha = ColorHasAlpha(DstFormat);
@ -1195,7 +1264,8 @@ BYTE* freerdp_bitmap_planar_delta_encode_plane(const BYTE* inPlane, UINT32 width
{
INT32 delta = *srcPtr - *prevLinePtr;
s2c = (delta >= 0) ? (char)delta : (char)(~((BYTE)(-delta)) + 1);
s2c = (s2c >= 0) ? ((UINT32)s2c << 1) : (char)(((UINT32)(~((BYTE)s2c) + 1) << 1) - 1);
s2c = (s2c >= 0) ? (char)((UINT32)s2c << 1)
: (char)(((UINT32)(~((BYTE)s2c) + 1) << 1) - 1);
*outPtr = (BYTE)s2c;
}
}
@ -1238,6 +1308,9 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, const BYTE*
planeSize = width * height;
if (!context->AllowSkipAlpha)
format = planar_invert_format(context, TRUE, format);
if (!freerdp_split_color_planes(data, format, width, height, scanline, context->planes))
return NULL;
@ -1393,6 +1466,7 @@ BOOL freerdp_bitmap_planar_context_reset(BITMAP_PLANAR_CONTEXT* context, UINT32
if (!context)
return FALSE;
context->bgr = FALSE;
context->maxWidth = width;
context->maxHeight = height;
context->maxPlaneSize = context->maxWidth * context->maxHeight;
@ -1464,3 +1538,8 @@ void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context)
free(context->rlePlanesBuffer);
free(context);
}
void freerdp_planar_switch_bgr(BITMAP_PLANAR_CONTEXT* planar, BOOL bgr)
{
planar->bgr = bgr;
}

View File

@ -396,6 +396,7 @@ static void progressive_surface_context_free(PROGRESSIVE_SURFACE_CONTEXT* surfac
}
free(surface->tiles);
free(surface->updatedTileIndices);
free(surface);
}
@ -449,8 +450,9 @@ static PROGRESSIVE_SURFACE_CONTEXT* progressive_surface_context_new(UINT16 surfa
surface->gridHeight = (height + (64 - height % 64)) / 64;
surface->gridSize = surface->gridWidth * surface->gridHeight;
surface->tiles = (RFX_PROGRESSIVE_TILE*)calloc(surface->gridSize, sizeof(RFX_PROGRESSIVE_TILE));
surface->updatedTileIndices = (UINT32*)calloc(surface->gridSize, sizeof(UINT32));
if (!surface->tiles)
if (!surface->tiles || !surface->updatedTileIndices)
{
free(surface);
return NULL;
@ -542,8 +544,14 @@ static BOOL progressive_surface_tile_replace(PROGRESSIVE_SURFACE_CONTEXT* surfac
region->numTiles, region->usedTiles);
return FALSE;
}
if (surface->numUpdatedTiles >= surface->gridSize)
{
WLog_ERR(TAG, "Invalid total tile count, maximum %" PRIu32, surface->gridSize);
return FALSE;
}
region->tiles[region->usedTiles++] = t;
surface->updatedTileIndices[surface->numUpdatedTiles++] = (UINT32)zIdx;
return TRUE;
}
@ -823,11 +831,10 @@ static INLINE int progressive_rfx_dwt_2d_decode(PROGRESSIVE_CONTEXT* progressive
temp = (INT16*)BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */
if (!temp)
return -2;
if (!extrapolate)
{
rfx_dwt_2d_decode_block(&buffer[3840], temp, 8);
rfx_dwt_2d_decode_block(&buffer[3072], temp, 16);
rfx_dwt_2d_decode_block(&buffer[0], temp, 32);
progressive->rfx_context->dwt_2d_decode(buffer, temp);
}
else
{
@ -857,28 +864,40 @@ static INLINE int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progress
int status;
const primitives_t* prims = primitives_get();
if (!subbandDiff)
WLog_WARN(TAG, "PROGRESSIVE_BLOCK_CONTEXT::flags & RFX_SUBBAND_DIFFING not set");
status = rfx_rlgr_decode(RLGR1, data, length, buffer, 4096);
status = progressive->rfx_context->rlgr_decode(RLGR1, data, length, buffer, 4096);
if (status < 0)
return status;
CopyMemory(sign, buffer, 4096 * 2);
progressive_rfx_decode_block(prims, &buffer[0], 1023, shift->HL1); /* HL1 */
progressive_rfx_decode_block(prims, &buffer[1023], 1023, shift->LH1); /* LH1 */
progressive_rfx_decode_block(prims, &buffer[2046], 961, shift->HH1); /* HH1 */
progressive_rfx_decode_block(prims, &buffer[3007], 272, shift->HL2); /* HL2 */
progressive_rfx_decode_block(prims, &buffer[3279], 272, shift->LH2); /* LH2 */
progressive_rfx_decode_block(prims, &buffer[3551], 256, shift->HH2); /* HH2 */
progressive_rfx_decode_block(prims, &buffer[3807], 72, shift->HL3); /* HL3 */
progressive_rfx_decode_block(prims, &buffer[3879], 72, shift->LH3); /* LH3 */
progressive_rfx_decode_block(prims, &buffer[3951], 64, shift->HH3); /* HH3 */
rfx_differential_decode(&buffer[4015], 81); /* LL3 */
progressive_rfx_decode_block(prims, &buffer[4015], 81, shift->LL3); /* LL3 */
if (!subbandDiff)
{
rfx_differential_decode(buffer + 4032, 64);
progressive_rfx_decode_block(prims, &buffer[0], 1024, shift->HL1); /* HL1 */
progressive_rfx_decode_block(prims, &buffer[1024], 1024, shift->LH1); /* LH1 */
progressive_rfx_decode_block(prims, &buffer[2048], 1024, shift->HH1); /* HH1 */
progressive_rfx_decode_block(prims, &buffer[3072], 256, shift->HL2); /* HL2 */
progressive_rfx_decode_block(prims, &buffer[3328], 256, shift->LH2); /* LH2 */
progressive_rfx_decode_block(prims, &buffer[3584], 256, shift->HH2); /* HH2 */
progressive_rfx_decode_block(prims, &buffer[3840], 64, shift->HL3); /* HL3 */
progressive_rfx_decode_block(prims, &buffer[3904], 64, shift->LH3); /* LH3 */
progressive_rfx_decode_block(prims, &buffer[3968], 64, shift->HH3); /* HH3 */
progressive_rfx_decode_block(prims, &buffer[4032], 64, shift->LL3); /* LL3 */
}
else
{
progressive_rfx_decode_block(prims, &buffer[0], 1023, shift->HL1); /* HL1 */
progressive_rfx_decode_block(prims, &buffer[1023], 1023, shift->LH1); /* LH1 */
progressive_rfx_decode_block(prims, &buffer[2046], 961, shift->HH1); /* HH1 */
progressive_rfx_decode_block(prims, &buffer[3007], 272, shift->HL2); /* HL2 */
progressive_rfx_decode_block(prims, &buffer[3279], 272, shift->LH2); /* LH2 */
progressive_rfx_decode_block(prims, &buffer[3551], 256, shift->HH2); /* HH2 */
progressive_rfx_decode_block(prims, &buffer[3807], 72, shift->HL3); /* HL3 */
progressive_rfx_decode_block(prims, &buffer[3879], 72, shift->LH3); /* LH3 */
progressive_rfx_decode_block(prims, &buffer[3951], 64, shift->HH3); /* HH3 */
rfx_differential_decode(&buffer[4015], 81); /* LL3 */
progressive_rfx_decode_block(prims, &buffer[4015], 81, shift->LL3); /* LL3 */
}
return progressive_rfx_dwt_2d_decode(progressive, buffer, current, coeffDiff, extrapolate,
FALSE);
}
@ -1008,7 +1027,6 @@ static INLINE int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progres
rc = progressive_rfx_decode_component(progressive, &shiftCr, tile->crData, tile->crLen,
pSrcDst[2], pCurrent[2], pSign[2], diff, sub,
extrapolate); /* Cr */
if (rc < 0)
goto fail;
@ -1722,7 +1740,7 @@ static INLINE int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, wS
}
}
return (int)end - start;
return (int)(end - start);
}
static INLINE INT32 progressive_wb_sync(PROGRESSIVE_CONTEXT* progressive, wStream* s,
@ -2137,9 +2155,18 @@ static INLINE INT32 progressive_wb_region(PROGRESSIVE_CONTEXT* progressive, wStr
INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize,
BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst,
UINT32 nYDst, REGION16* invalidRegion, UINT16 surfaceId)
{
return progressive_decompress_ex(progressive, pSrcData, SrcSize, pDstData, DstFormat, nDstStep,
nXDst, nYDst, invalidRegion, surfaceId, 0);
}
INT32 progressive_decompress_ex(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
UINT32 SrcSize, BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
UINT32 nXDst, UINT32 nYDst, REGION16* invalidRegion,
UINT16 surfaceId, UINT32 frameId)
{
INT32 rc = 1;
UINT16 i, j;
UINT32 i, j;
UINT16 blockType;
UINT32 blockLen;
UINT32 count = 0;
@ -2162,6 +2189,12 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD
return -1001;
}
if (surface->frameId != frameId)
{
surface->frameId = frameId;
surface->numUpdatedTiles = 0;
}
Stream_StaticInit(&ss, sconv.bp, SrcSize);
s = &ss;
@ -2264,12 +2297,12 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD
region16_union_rect(&clippingRects, &clippingRects, &clippingRect);
}
for (i = 0; i < region->numTiles; i++)
for (i = 0; i < surface->numUpdatedTiles; i++)
{
UINT32 nbUpdateRects;
const RECTANGLE_16* updateRects;
RECTANGLE_16 updateRect;
RFX_PROGRESSIVE_TILE* tile = region->tiles[i];
RFX_PROGRESSIVE_TILE* tile = &surface->tiles[surface->updatedTileIndices[i]];
updateRect.left = nXDst + tile->x;
updateRect.top = nYDst + tile->y;
@ -2308,12 +2341,261 @@ fail:
return rc;
}
static BOOL progressive_rfx_write_message_progressive_simple(RFX_CONTEXT* context, wStream* s,
RFX_MESSAGE* msg)
{
UINT32 blockLen;
UINT32 i;
UINT32* qv;
RFX_TILE* tile;
UINT32 tilesDataSize;
if (context->mode != RLGR1)
{
WLog_ERR(TAG, "%s: error, RLGR1 mode is required!", __FUNCTION__);
return FALSE;
}
/* RFX_PROGRESSIVE_SYNC */
blockLen = 12;
if (!Stream_EnsureRemainingCapacity(s, blockLen))
{
return FALSE;
}
Stream_Write_UINT16(s, 0xCCC0); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT32(s, 0xCACCACCA); /* magic (4 bytes) */
Stream_Write_UINT16(s, 0x0100); /* version (2 bytes) */
/* RFX_PROGRESSIVE_CONTEXT */
blockLen = 10;
if (!Stream_EnsureRemainingCapacity(s, blockLen))
{
return FALSE;
}
Stream_Write_UINT16(s, 0xCCC3); /* blockType (2 bytes) */
Stream_Write_UINT32(s, 10); /* blockLen (4 bytes) */
Stream_Write_UINT8(s, 0); /* ctxId (1 byte) */
Stream_Write_UINT16(s, 64); /* tileSize (2 bytes) */
Stream_Write_UINT8(s, 0); /* flags (1 byte) */
/* RFX_PROGRESSIVE_FRAME_BEGIN */
blockLen = 12;
if (!Stream_EnsureRemainingCapacity(s, blockLen))
{
return FALSE;
}
Stream_Write_UINT16(s, 0xCCC1); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT32(s, msg->frameIdx); /* frameIndex (4 bytes) */
Stream_Write_UINT16(s, 1); /* regionCount (2 bytes) */
/* RFX_PROGRESSIVE_REGION */
blockLen = 18;
blockLen += msg->numRects * 8;
blockLen += msg->numQuant * 5;
tilesDataSize = msg->numTiles * 22;
for (i = 0; i < msg->numTiles; i++)
{
tile = msg->tiles[i];
tilesDataSize += tile->YLen + tile->CbLen + tile->CrLen;
}
blockLen += tilesDataSize;
if (!Stream_EnsureRemainingCapacity(s, blockLen))
{
return FALSE;
}
Stream_Write_UINT16(s, 0xCCC4); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT8(s, 64); /* tileSize (1 byte) */
Stream_Write_UINT16(s, msg->numRects); /* numRects (2 bytes) */
Stream_Write_UINT8(s, msg->numQuant); /* numQuant (1 byte) */
Stream_Write_UINT8(s, 0); /* numProgQuant (1 byte) */
Stream_Write_UINT8(s, 0); /* flags (1 byte) */
Stream_Write_UINT16(s, msg->numTiles); /* numTiles (2 bytes) */
Stream_Write_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */
for (i = 0; i < msg->numRects; i++)
{
/* TS_RFX_RECT */
Stream_Write_UINT16(s, msg->rects[i].x); /* x (2 bytes) */
Stream_Write_UINT16(s, msg->rects[i].y); /* y (2 bytes) */
Stream_Write_UINT16(s, msg->rects[i].width); /* width (2 bytes) */
Stream_Write_UINT16(s, msg->rects[i].height); /* height (2 bytes) */
}
/**
* Note: The RFX_COMPONENT_CODEC_QUANT structure differs from the
* TS_RFX_CODEC_QUANT ([MS-RDPRFX] section 2.2.2.1.5) structure with respect
* to the order of the bands.
* 0 1 2 3 4 5 6 7 8 9
* RDPRFX: LL3, LH3, HL3, HH3, LH2, HL2, HH2, LH1, HL1, HH1
* RDPEGFX: LL3, HL3, LH3, HH3, HL2, LH2, HH2, HL1, LH1, HH1
*/
for (i = 0, qv = msg->quantVals; i < msg->numQuant; i++, qv += 10)
{
/* RFX_COMPONENT_CODEC_QUANT */
Stream_Write_UINT8(s, qv[0] + (qv[2] << 4)); /* LL3 (4-bit), HL3 (4-bit) */
Stream_Write_UINT8(s, qv[1] + (qv[3] << 4)); /* LH3 (4-bit), HH3 (4-bit) */
Stream_Write_UINT8(s, qv[5] + (qv[4] << 4)); /* HL2 (4-bit), LH2 (4-bit) */
Stream_Write_UINT8(s, qv[6] + (qv[8] << 4)); /* HH2 (4-bit), HL1 (4-bit) */
Stream_Write_UINT8(s, qv[7] + (qv[9] << 4)); /* LH1 (4-bit), HH1 (4-bit) */
}
for (i = 0; i < msg->numTiles; i++)
{
/* RFX_PROGRESSIVE_TILE_SIMPLE */
tile = msg->tiles[i];
blockLen = 22 + tile->YLen + tile->CbLen + tile->CrLen;
Stream_Write_UINT16(s, 0xCCC5); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT8(s, tile->quantIdxY); /* quantIdxY (1 byte) */
Stream_Write_UINT8(s, tile->quantIdxCb); /* quantIdxCb (1 byte) */
Stream_Write_UINT8(s, tile->quantIdxCr); /* quantIdxCr (1 byte) */
Stream_Write_UINT16(s, tile->xIdx); /* xIdx (2 bytes) */
Stream_Write_UINT16(s, tile->yIdx); /* yIdx (2 bytes) */
Stream_Write_UINT8(s, 0); /* flags (1 byte) */
Stream_Write_UINT16(s, tile->YLen); /* YLen (2 bytes) */
Stream_Write_UINT16(s, tile->CbLen); /* CbLen (2 bytes) */
Stream_Write_UINT16(s, tile->CrLen); /* CrLen (2 bytes) */
Stream_Write_UINT16(s, 0); /* tailLen (2 bytes) */
Stream_Write(s, tile->YData, tile->YLen); /* YData */
Stream_Write(s, tile->CbData, tile->CbLen); /* CbData */
Stream_Write(s, tile->CrData, tile->CrLen); /* CrData */
}
/* RFX_PROGRESSIVE_FRAME_END */
blockLen = 6;
if (!Stream_EnsureRemainingCapacity(s, blockLen))
{
return FALSE;
}
Stream_Write_UINT16(s, 0xCCC2); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
return TRUE;
}
int progressive_compress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize,
BYTE** ppDstData, UINT32* pDstSize)
{
return -1;
}
int progressive_compress_ex(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize,
UINT32 SrcFormat, UINT32 Width, UINT32 Height, UINT32 ScanLine,
const REGION16* invalidRegion, BYTE** ppDstData, UINT32* pDstSize)
{
BOOL rc;
int res = -6;
wStream* s;
UINT32 i, numRects;
UINT32 x, y;
RFX_RECT* rects = NULL;
RFX_MESSAGE* message;
if (!progressive || !pSrcData || !ppDstData || !pDstSize)
{
return -1;
}
if (ScanLine == 0)
{
switch (SrcFormat)
{
case PIXEL_FORMAT_ABGR32:
case PIXEL_FORMAT_ARGB32:
case PIXEL_FORMAT_XBGR32:
case PIXEL_FORMAT_XRGB32:
case PIXEL_FORMAT_BGRA32:
case PIXEL_FORMAT_BGRX32:
case PIXEL_FORMAT_RGBA32:
case PIXEL_FORMAT_RGBX32:
ScanLine = Width * 4;
break;
default:
return -2;
}
}
if (ScanLine / Width != 4)
return -3;
if (SrcSize < Height * ScanLine)
return -4;
if (!invalidRegion)
{
numRects = (Width + 63) / 64;
numRects *= (Height + 63) / 64;
}
else
numRects = region16_n_rects(invalidRegion);
if (numRects == 0)
return 0;
if (!Stream_EnsureCapacity(progressive->rects, numRects * sizeof(RFX_RECT)))
return -5;
rects = (RFX_RECT*)Stream_Buffer(progressive->rects);
if (invalidRegion)
{
RECTANGLE_16* r = region16_rects(invalidRegion, NULL);
for (x = 0; x < numRects; x++)
{
rects[x].x = r[x].left;
rects[x].y = r[x].top;
rects[x].width = r[x].right - r[x].left;
rects[x].height = r[x].bottom - r[x].top;
}
}
else
{
x = 0;
y = 0;
for (i = 0; i < numRects; i++)
{
RFX_RECT* r = &rects[i];
r->x = x;
r->y = y;
r->width = MIN(64, Width - x);
r->height = MIN(64, Height - y);
if (x + 64 >= Width)
{
y += 64;
x = 0;
}
else
x += 64;
}
}
s = progressive->buffer;
Stream_SetPosition(s, 0);
progressive->rfx_context->mode = RLGR1;
message = rfx_encode_message(progressive->rfx_context, rects, numRects, pSrcData, Width, Height,
ScanLine);
if (!message)
{
WLog_ERR(TAG, "failed to encode rfx message");
goto fail;
}
message->freeRects = TRUE;
rc = progressive_rfx_write_message_progressive_simple(progressive->rfx_context, s, message);
rfx_message_free(progressive->rfx_context, message);
if (!rc)
goto fail;
*pDstSize = Stream_GetPosition(s);
*ppDstData = Stream_Buffer(s);
res = 0;
fail:
return res;
}
BOOL progressive_context_reset(PROGRESSIVE_CONTEXT* progressive)
{
if (!progressive)
@ -2324,22 +2606,38 @@ BOOL progressive_context_reset(PROGRESSIVE_CONTEXT* progressive)
PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor)
{
PROGRESSIVE_CONTEXT* progressive;
progressive = (PROGRESSIVE_CONTEXT*)calloc(1, sizeof(PROGRESSIVE_CONTEXT));
PROGRESSIVE_CONTEXT* progressive = (PROGRESSIVE_CONTEXT*)calloc(1, sizeof(PROGRESSIVE_CONTEXT));
if (progressive)
{
progressive->Compressor = Compressor;
progressive->bufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16);
if (!progressive)
return NULL;
ZeroMemory(&(progressive->quantProgValFull), sizeof(RFX_PROGRESSIVE_CODEC_QUANT));
progressive->quantProgValFull.quality = 100;
progressive->SurfaceContexts = HashTable_New(TRUE);
progressive_context_reset(progressive);
progressive->log = WLog_Get(TAG);
}
progressive->Compressor = Compressor;
progressive->quantProgValFull.quality = 100;
progressive->log = WLog_Get(TAG);
if (!progressive->log)
goto fail;
progressive->rfx_context = rfx_context_new(Compressor);
if (!progressive->rfx_context)
goto fail;
progressive->buffer = Stream_New(NULL, 1024);
if (!progressive->buffer)
goto fail;
progressive->rects = Stream_New(NULL, 1024);
if (!progressive->rects)
goto fail;
progressive->bufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16);
if (!progressive->bufferPool)
goto fail;
progressive->SurfaceContexts = HashTable_New(TRUE);
if (!progressive->SurfaceContexts)
goto fail;
if (!progressive_context_reset(progressive))
goto fail;
return progressive;
fail:
progressive_context_free(progressive);
return NULL;
}
void progressive_context_free(PROGRESSIVE_CONTEXT* progressive)
@ -2352,6 +2650,10 @@ void progressive_context_free(PROGRESSIVE_CONTEXT* progressive)
if (!progressive)
return;
Stream_Free(progressive->buffer, TRUE);
Stream_Free(progressive->rects, TRUE);
rfx_context_free(progressive->rfx_context);
BufferPool_Free(progressive->bufferPool);
if (progressive->SurfaceContexts)

View File

@ -200,6 +200,9 @@ struct _PROGRESSIVE_SURFACE_CONTEXT
UINT32 gridHeight;
UINT32 gridSize;
RFX_PROGRESSIVE_TILE* tiles;
UINT32 frameId;
UINT32 numUpdatedTiles;
UINT32* updatedTileIndices;
};
typedef struct _PROGRESSIVE_SURFACE_CONTEXT PROGRESSIVE_SURFACE_CONTEXT;
@ -228,6 +231,9 @@ struct _PROGRESSIVE_CONTEXT
wHashTable* SurfaceContexts;
wLog* log;
wStream* buffer;
wStream* rects;
RFX_CONTEXT* rfx_context;
};
#endif /* INTERNAL_CODEC_PROGRESSIVE_H */

View File

@ -220,9 +220,6 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder)
priv->log = WLog_Get("com.freerdp.codec.rfx");
WLog_OpenAppender(priv->log);
#ifdef WITH_DEBUG_RFX
WLog_SetLogLevel(priv->log, WLOG_DEBUG);
#endif
priv->TilePool = ObjectPool_New(TRUE);
if (!priv->TilePool)
@ -388,6 +385,11 @@ static RFX_TILE* rfx_message_get_tile(RFX_MESSAGE* message, UINT32 index)
return message->tiles[index];
}
static const RFX_RECT* rfx_message_get_rect_const(const RFX_MESSAGE* message, UINT32 index)
{
return &message->rects[index];
}
static RFX_RECT* rfx_message_get_rect(RFX_MESSAGE* message, UINT32 index)
{
return &message->rects[index];
@ -640,7 +642,7 @@ static BOOL rfx_process_message_frame_end(RFX_CONTEXT* context, RFX_MESSAGE* mes
static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s,
UINT16* pExpectedBlockType)
{
int i;
UINT16 i;
UINT16 regionType;
UINT16 numTileSets;
RFX_RECT* tmpRects;
@ -1431,8 +1433,8 @@ static BOOL setupWorkers(RFX_CONTEXT* context, int nbTiles)
return TRUE;
}
RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects,
BYTE* data, int w, int h, int s)
RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, size_t numRects,
const BYTE* data, UINT32 w, UINT32 h, size_t s)
{
const UINT32 width = (UINT32)w;
const UINT32 height = (UINT32)h;
@ -1570,7 +1572,8 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int
tile->allocated = FALSE;
}
tile->data = &data[(ay * scanline) + (ax * bytesPerPixel)];
/* Cast away const */
tile->data = (BYTE*)&data[(ay * scanline) + (ax * bytesPerPixel)];
tile->quantIdxY = context->quantIdxY;
tile->quantIdxCb = context->quantIdxCb;
tile->quantIdxCr = context->quantIdxCr;
@ -1666,10 +1669,10 @@ skip_encoding_loop:
return NULL;
}
static RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message, int* numMessages,
int maxDataSize)
static RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message,
size_t* numMessages, size_t maxDataSize)
{
int i, j;
size_t i, j;
UINT32 tileDataSize;
RFX_MESSAGE* messages;
maxDataSize -= 1024; /* reserve enough space for headers */
@ -1719,9 +1722,9 @@ free_messages:
return NULL;
}
RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects,
BYTE* data, int width, int height, int scanline, int* numMessages,
int maxDataSize)
RFX_MESSAGE* rfx_encode_messages_ex(RFX_CONTEXT* context, const RFX_RECT* rects, size_t numRects,
const BYTE* data, UINT32 width, UINT32 height, UINT32 scanline,
size_t* numMessages, size_t maxDataSize)
{
RFX_MESSAGE* message;
RFX_MESSAGE* messageList;
@ -1740,7 +1743,7 @@ RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, in
return messageList;
}
static BOOL rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message)
static BOOL rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, const RFX_MESSAGE* message)
{
int i;
RFX_TILE* tile;
@ -1787,7 +1790,8 @@ static BOOL rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, RFX_MESS
return TRUE;
}
static BOOL rfx_write_message_frame_begin(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message)
static BOOL rfx_write_message_frame_begin(RFX_CONTEXT* context, wStream* s,
const RFX_MESSAGE* message)
{
if (!Stream_EnsureRemainingCapacity(s, 14))
return FALSE;
@ -1801,7 +1805,7 @@ static BOOL rfx_write_message_frame_begin(RFX_CONTEXT* context, wStream* s, RFX_
return TRUE;
}
static BOOL rfx_write_message_region(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message)
static BOOL rfx_write_message_region(RFX_CONTEXT* context, wStream* s, const RFX_MESSAGE* message)
{
int i;
UINT32 blockLen;
@ -1819,7 +1823,7 @@ static BOOL rfx_write_message_region(RFX_CONTEXT* context, wStream* s, RFX_MESSA
for (i = 0; i < message->numRects; i++)
{
const RFX_RECT* rect = rfx_message_get_rect(message, i);
const RFX_RECT* rect = rfx_message_get_rect_const(message, i);
/* Clipping rectangles are relative to destLeft, destTop */
Stream_Write_UINT16(s, rect->x); /* x (2 bytes) */
Stream_Write_UINT16(s, rect->y); /* y (2 bytes) */
@ -1832,7 +1836,8 @@ static BOOL rfx_write_message_region(RFX_CONTEXT* context, wStream* s, RFX_MESSA
return TRUE;
}
static BOOL rfx_write_message_frame_end(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message)
static BOOL rfx_write_message_frame_end(RFX_CONTEXT* context, wStream* s,
const RFX_MESSAGE* message)
{
if (!Stream_EnsureRemainingCapacity(s, 8))
return FALSE;
@ -1844,7 +1849,7 @@ static BOOL rfx_write_message_frame_end(RFX_CONTEXT* context, wStream* s, RFX_ME
return TRUE;
}
BOOL rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message)
BOOL rfx_write_message(RFX_CONTEXT* context, wStream* s, const RFX_MESSAGE* message)
{
if (context->state == RFX_STATE_SEND_HEADERS)
{
@ -1865,8 +1870,8 @@ BOOL rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message)
return TRUE;
}
BOOL rfx_compose_message(RFX_CONTEXT* context, wStream* s, const RFX_RECT* rects, int numRects,
BYTE* data, int width, int height, int scanline)
BOOL rfx_compose_message(RFX_CONTEXT* context, wStream* s, const RFX_RECT* rects, size_t numRects,
const BYTE* data, UINT32 width, UINT32 height, UINT32 scanline)
{
RFX_MESSAGE* message;
BOOL ret = TRUE;
@ -1879,3 +1884,15 @@ BOOL rfx_compose_message(RFX_CONTEXT* context, wStream* s, const RFX_RECT* rects
rfx_message_free(context, message);
return ret;
}
RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects,
const BYTE* data, int width, int height, int scanline,
int* numMessages, int maxDataSize)
{
size_t tmp;
RFX_MESSAGE* msg = rfx_encode_messages_ex(context, rects, numRects, data, width, height,
scanline, &tmp, maxDataSize);
if (numMessages)
*numMessages = tmp;
return msg;
}

View File

@ -37,8 +37,8 @@
#include "rfx_decode.h"
static void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantization_values,
const BYTE* data, int size, INT16* buffer)
void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantization_values, const BYTE* data,
int size, INT16* buffer)
{
INT16* dwt_buffer;
dwt_buffer = BufferPool_Take(context->priv->BufferPool, -1); /* dwt_buffer */
@ -62,7 +62,7 @@ static void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantizatio
/* rfx_decode_ycbcr_to_rgb code now resides in the primitives library. */
/* stride is bytes between rows in the output buffer. */
BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int stride)
BOOL rfx_decode_rgb(RFX_CONTEXT* context, const RFX_TILE* tile, BYTE* rgb_buffer, UINT32 stride)
{
BOOL rc = TRUE;
BYTE* pBuffer;

View File

@ -24,7 +24,8 @@
#include <freerdp/api.h>
/* stride is bytes between rows in the output buffer. */
FREERDP_LOCAL BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer,
int stride);
FREERDP_LOCAL BOOL rfx_decode_rgb(RFX_CONTEXT* context, const RFX_TILE* tile, BYTE* rgb_buffer,
UINT32 stride);
FREERDP_LOCAL void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantization_values,
const BYTE* data, int size, INT16* buffer);
#endif /* FREERDP_LIB_CODEC_RFX_DECODE_H */

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