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:
commit
0dc851016e
71
.github/workflows/codeql-analysis.yml
vendored
Normal file
71
.github/workflows/codeql-analysis.yml
vendored
Normal 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
|
||||
@ -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
|
||||
|
||||
@ -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")
|
||||
|
||||
35
ChangeLog
35
ChangeLog
@ -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:
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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})
|
||||
|
||||
@ -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);
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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) */
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -49,6 +49,7 @@ struct cliprdr_plugin
|
||||
BOOL streamFileClipEnabled;
|
||||
BOOL fileClipNoFilePaths;
|
||||
BOOL canLockClipData;
|
||||
BOOL hasHugeFileSupport;
|
||||
};
|
||||
typedef struct cliprdr_plugin cliprdrPlugin;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -85,6 +85,7 @@ struct _RDPGFX_PLUGIN
|
||||
wLog* log;
|
||||
RDPGFX_CAPSET ConnectionCaps;
|
||||
BOOL SendQoeAck;
|
||||
BOOL initialized;
|
||||
};
|
||||
typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN;
|
||||
|
||||
|
||||
@ -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) */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
546
channels/smartcard/client/smartcard_operations.h
Normal file
546
channels/smartcard/client/smartcard_operations.h
Normal 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
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -63,7 +63,7 @@ struct _UDEVICE
|
||||
MSUSB_CONFIG_DESCRIPTOR* MsConfig;
|
||||
LIBUSB_CONFIG_DESCRIPTOR* LibusbConfig;
|
||||
|
||||
wHashTable* request_queue;
|
||||
wArrayList* request_queue;
|
||||
|
||||
URBDRC_PLUGIN* urbdrc;
|
||||
};
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -42,6 +42,8 @@ struct wlf_context
|
||||
UwacSeat* seat;
|
||||
|
||||
BOOL fullscreen;
|
||||
BOOL closed;
|
||||
BOOL focusing;
|
||||
|
||||
/* Channels */
|
||||
RdpeiClientContext* rdpei;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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, ¤t) == 0)
|
||||
rc = XGetWindowAttributes(xfc->display, handle, ¤t);
|
||||
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);
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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")
|
||||
{
|
||||
|
||||
@ -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" },
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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})
|
||||
|
||||
@ -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")
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -24,4 +24,6 @@
|
||||
#include <freerdp/dvc.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#define AUDIN_DVC_CHANNEL_NAME "AUDIO_INPUT"
|
||||
|
||||
#endif /* FREERDP_CHANNEL_AUDIN_H */
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
30
include/freerdp/channels/echo.h
Normal file
30
include/freerdp/channels/echo.h
Normal 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 */
|
||||
@ -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 */
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -525,6 +525,7 @@ struct rdp_gdi
|
||||
GeometryClientContext* geometry;
|
||||
|
||||
wLog* log;
|
||||
UINT32 frameId;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -126,6 +126,7 @@ struct _cliprdr_server_context
|
||||
rdpContext* rdpcontext;
|
||||
BOOL autoInitializationSequence;
|
||||
UINT32 lastRequestedFormatId;
|
||||
BOOL hasHugeFileSupport;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
Loading…
Reference in New Issue
Block a user