diff -Nru freerdp2-2.2.0+dfsg1/ChangeLog freerdp2-2.3.0+dfsg1/ChangeLog --- freerdp2-2.2.0+dfsg1/ChangeLog 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/ChangeLog 2021-02-25 08:51:41.000000000 +0000 @@ -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: diff -Nru freerdp2-2.2.0+dfsg1/channels/audin/client/audin_main.c freerdp2-2.3.0+dfsg1/channels/audin/client/audin_main.c --- freerdp2-2.2.0+dfsg1/channels/audin/client/audin_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/audin/client/audin_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -39,6 +39,7 @@ #include #include #include +#include #include "audin_main.h" @@ -102,6 +103,8 @@ 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_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { + UINT rc; AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin; if (!audin) @@ -676,6 +680,12 @@ 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 @@ 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; } /** diff -Nru freerdp2-2.2.0+dfsg1/channels/audin/client/mac/audin_mac.c freerdp2-2.3.0+dfsg1/channels/audin/client/mac/audin_mac.c --- freerdp2-2.2.0+dfsg1/channels/audin/client/mac/audin_mac.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/audin/client/mac/audin_mac.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,410 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Audio Input Redirection Virtual Channel - Mac OS X implementation - * - * Copyright (c) 2015 Armin Novak - * Copyright 2015 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define __COREFOUNDATION_CFPLUGINCOM__ 1 -#define IUNKNOWN_C_GUTS \ - void* _reserved; \ - void* QueryInterface; \ - void* AddRef; \ - void* Release - -#include -#include -#include -#include - -#include -#include - -#include "audin_main.h" - -#define MAC_AUDIO_QUEUE_NUM_BUFFERS 100 - -/* Fix for #4462: Provide type alias if not declared (Mac OS < 10.10) - * https://developer.apple.com/documentation/coreaudio/audioformatid - */ -#ifndef AudioFormatID -typedef UInt32 AudioFormatID; -#endif - -#ifndef AudioFormatFlags -typedef UInt32 AudioFormatFlags; -#endif - -typedef struct _AudinMacDevice -{ - IAudinDevice iface; - - AUDIO_FORMAT format; - UINT32 FramesPerPacket; - int dev_unit; - - AudinReceive receive; - void* user_data; - - rdpContext* rdpcontext; - - bool isOpen; - AudioQueueRef audioQueue; - AudioStreamBasicDescription audioFormat; - AudioQueueBufferRef audioBuffers[MAC_AUDIO_QUEUE_NUM_BUFFERS]; -} AudinMacDevice; - -static AudioFormatID audin_mac_get_format(const AUDIO_FORMAT* format) -{ - switch (format->wFormatTag) - { - case WAVE_FORMAT_PCM: - return kAudioFormatLinearPCM; - - default: - return 0; - } -} - -static AudioFormatFlags audin_mac_get_flags_for_format(const AUDIO_FORMAT* format) -{ - switch (format->wFormatTag) - { - case WAVE_FORMAT_PCM: - return kAudioFormatFlagIsSignedInteger; - - default: - return 0; - } -} - -static BOOL audin_mac_format_supported(IAudinDevice* device, const AUDIO_FORMAT* format) -{ - AudioFormatID req_fmt = 0; - - if (device == NULL || format == NULL) - return FALSE; - - req_fmt = audin_mac_get_format(format); - - if (req_fmt == 0) - return FALSE; - - return TRUE; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT audin_mac_set_format(IAudinDevice* device, const AUDIO_FORMAT* format, - UINT32 FramesPerPacket) -{ - AudinMacDevice* mac = (AudinMacDevice*)device; - - if (device == NULL || format == NULL) - return ERROR_INVALID_PARAMETER; - - mac->FramesPerPacket = FramesPerPacket; - mac->format = *format; - WLog_INFO(TAG, "Audio Format %s [channels=%d, samples=%d, bits=%d]", - audio_format_get_tag_string(format->wFormatTag), format->nChannels, - format->nSamplesPerSec, format->wBitsPerSample); - mac->audioFormat.mBitsPerChannel = format->wBitsPerSample; - - if (format->wBitsPerSample == 0) - mac->audioFormat.mBitsPerChannel = 16; - - mac->audioFormat.mBytesPerFrame = 0; - mac->audioFormat.mBytesPerPacket = 0; - mac->audioFormat.mChannelsPerFrame = mac->format.nChannels; - mac->audioFormat.mFormatFlags = audin_mac_get_flags_for_format(format); - mac->audioFormat.mFormatID = audin_mac_get_format(format); - mac->audioFormat.mFramesPerPacket = 1; - mac->audioFormat.mReserved = 0; - mac->audioFormat.mSampleRate = mac->format.nSamplesPerSec; - 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) -{ - AudinMacDevice* mac = (AudinMacDevice*)aqData; - UINT error = CHANNEL_RC_OK; - const BYTE* buffer = inBuffer->mAudioData; - int buffer_size = inBuffer->mAudioDataByteSize; - (void)inAQ; - (void)inStartTime; - (void)inNumPackets; - (void)inPacketDesc; - - if (buffer_size > 0) - error = mac->receive(&mac->format, buffer, buffer_size, mac->user_data); - - AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL); - - if (error) - { - WLog_ERR(TAG, "mac->receive failed with error %" PRIu32 "", error); - SetLastError(ERROR_INTERNAL_ERROR); - } -} - -static UINT audin_mac_close(IAudinDevice* device) -{ - UINT errCode = CHANNEL_RC_OK; - char errString[1024]; - OSStatus devStat; - AudinMacDevice* mac = (AudinMacDevice*)device; - - if (device == NULL) - return ERROR_INVALID_PARAMETER; - - if (mac->isOpen) - { - devStat = AudioQueueStop(mac->audioQueue, true); - - if (devStat != 0) - { - errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueStop failed with %s [%" PRIu32 "]", - winpr_strerror(errCode, errString, sizeof(errString)), errCode); - } - - mac->isOpen = false; - } - - if (mac->audioQueue) - { - devStat = AudioQueueDispose(mac->audioQueue, true); - - if (devStat != 0) - { - errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueDispose failed with %s [%" PRIu32 "]", - winpr_strerror(errCode, errString, sizeof(errString)), errCode); - } - - mac->audioQueue = NULL; - } - - mac->receive = NULL; - mac->user_data = NULL; - return errCode; -} - -static UINT audin_mac_open(IAudinDevice* device, AudinReceive receive, void* user_data) -{ - AudinMacDevice* mac = (AudinMacDevice*)device; - DWORD errCode; - char errString[1024]; - OSStatus devStat; - size_t index; - mac->receive = receive; - mac->user_data = user_data; - devStat = AudioQueueNewInput(&(mac->audioFormat), mac_audio_queue_input_cb, mac, NULL, - kCFRunLoopCommonModes, 0, &(mac->audioQueue)); - - if (devStat != 0) - { - errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueNewInput failed with %s [%" PRIu32 "]", - winpr_strerror(errCode, errString, sizeof(errString)), errCode); - goto err_out; - } - - for (index = 0; index < MAC_AUDIO_QUEUE_NUM_BUFFERS; index++) - { - devStat = AudioQueueAllocateBuffer(mac->audioQueue, - mac->FramesPerPacket * 2 * mac->format.nChannels, - &mac->audioBuffers[index]); - - if (devStat != 0) - { - errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueAllocateBuffer failed with %s [%" PRIu32 "]", - winpr_strerror(errCode, errString, sizeof(errString)), errCode); - goto err_out; - } - - devStat = AudioQueueEnqueueBuffer(mac->audioQueue, mac->audioBuffers[index], 0, NULL); - - if (devStat != 0) - { - errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueEnqueueBuffer failed with %s [%" PRIu32 "]", - winpr_strerror(errCode, errString, sizeof(errString)), errCode); - goto err_out; - } - } - - devStat = AudioQueueStart(mac->audioQueue, NULL); - - if (devStat != 0) - { - errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueStart failed with %s [%" PRIu32 "]", - winpr_strerror(errCode, errString, sizeof(errString)), errCode); - goto err_out; - } - - mac->isOpen = true; - return CHANNEL_RC_OK; -err_out: - audin_mac_close(device); - return CHANNEL_RC_INITIALIZATION_ERROR; -} - -static UINT audin_mac_free(IAudinDevice* device) -{ - AudinMacDevice* mac = (AudinMacDevice*)device; - int error; - - if (device == NULL) - return ERROR_INVALID_PARAMETER; - - if ((error = audin_mac_close(device))) - { - WLog_ERR(TAG, "audin_oss_close failed with error code %d!", error); - } - - free(mac); - return CHANNEL_RC_OK; -} - -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 audin_mac_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "", - NULL, NULL, -1, NULL, "audio device name" }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; - - AudinMacDevice* mac = (AudinMacDevice*)device; - - if (args->argc == 1) - return CHANNEL_RC_OK; - - flags = - COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; - status = - CommandLineParseArgumentsA(args->argc, args->argv, audin_mac_args, flags, mac, NULL, NULL); - - if (status < 0) - return ERROR_INVALID_PARAMETER; - - arg = audin_mac_args; - - do - { - if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) - continue; - - CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dev") - { - str_num = _strdup(arg->Value); - - if (!str_num) - { - errCode = GetLastError(); - WLog_ERR(TAG, "_strdup failed with %s [%d]", - winpr_strerror(errCode, errString, sizeof(errString)), errCode); - return CHANNEL_RC_NO_MEMORY; - } - - mac->dev_unit = strtol(str_num, &eptr, 10); - - if (mac->dev_unit < 0 || *eptr != '\0') - mac->dev_unit = -1; - - free(str_num); - } - CommandLineSwitchEnd(arg) - } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); - - return CHANNEL_RC_OK; -} - -#ifdef BUILTIN_CHANNELS -#define freerdp_audin_client_subsystem_entry mac_freerdp_audin_client_subsystem_entry -#else -#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry -#endif - -UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) -{ - DWORD errCode; - char errString[1024]; - ADDIN_ARGV* args; - AudinMacDevice* mac; - UINT error; - mac = (AudinMacDevice*)calloc(1, sizeof(AudinMacDevice)); - - if (!mac) - { - errCode = GetLastError(); - WLog_ERR(TAG, "calloc failed with %s [%" PRIu32 "]", - winpr_strerror(errCode, errString, sizeof(errString)), errCode); - return CHANNEL_RC_NO_MEMORY; - } - - mac->iface.Open = audin_mac_open; - mac->iface.FormatSupported = audin_mac_format_supported; - mac->iface.SetFormat = audin_mac_set_format; - mac->iface.Close = audin_mac_close; - mac->iface.Free = audin_mac_free; - mac->rdpcontext = pEntryPoints->rdpcontext; - mac->dev_unit = -1; - args = pEntryPoints->args; - - if ((error = audin_mac_parse_addin_args(mac, args))) - { - WLog_ERR(TAG, "audin_mac_parse_addin_args failed with %" PRIu32 "!", error); - goto error_out; - } - - if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)mac))) - { - WLog_ERR(TAG, "RegisterAudinDevice failed with error %" PRIu32 "!", error); - goto error_out; - } - - return CHANNEL_RC_OK; -error_out: - free(mac); - return error; -} diff -Nru freerdp2-2.2.0+dfsg1/channels/audin/client/mac/audin_mac.m freerdp2-2.3.0+dfsg1/channels/audin/client/mac/audin_mac.m --- freerdp2-2.2.0+dfsg1/channels/audin/client/mac/audin_mac.m 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/audin/client/mac/audin_mac.m 2021-02-25 08:51:41.000000000 +0000 @@ -0,0 +1,455 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Audio Input Redirection Virtual Channel - Mac OS X implementation + * + * Copyright (c) 2015 Armin Novak + * Copyright 2015 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#import + +#define __COREFOUNDATION_CFPLUGINCOM__ 1 +#define IUNKNOWN_C_GUTS \ + void *_reserved; \ + void *QueryInterface; \ + void *AddRef; \ + void *Release + +#include +#include +#include +#include + +#include +#include + +#include "audin_main.h" + +#define MAC_AUDIO_QUEUE_NUM_BUFFERS 100 + +/* Fix for #4462: Provide type alias if not declared (Mac OS < 10.10) + * https://developer.apple.com/documentation/coreaudio/audioformatid + */ +#ifndef AudioFormatID +typedef UInt32 AudioFormatID; +#endif + +#ifndef AudioFormatFlags +typedef UInt32 AudioFormatFlags; +#endif + +typedef struct _AudinMacDevice +{ + IAudinDevice iface; + + AUDIO_FORMAT format; + UINT32 FramesPerPacket; + int dev_unit; + + AudinReceive receive; + void *user_data; + + 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) +{ + switch (format->wFormatTag) + { + case WAVE_FORMAT_PCM: + return kAudioFormatLinearPCM; + + default: + return 0; + } +} + +static AudioFormatFlags audin_mac_get_flags_for_format(const AUDIO_FORMAT *format) +{ + switch (format->wFormatTag) + { + case WAVE_FORMAT_PCM: + return kAudioFormatFlagIsSignedInteger; + + default: + return 0; + } +} + +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; + + req_fmt = audin_mac_get_format(format); + + if (req_fmt == 0) + return FALSE; + + return TRUE; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT audin_mac_set_format(IAudinDevice *device, const AUDIO_FORMAT *format, + UINT32 FramesPerPacket) +{ + AudinMacDevice *mac = (AudinMacDevice *)device; + + if (!mac->isAuthorized) + return ERROR_INTERNAL_ERROR; + + if (device == NULL || format == NULL) + return ERROR_INVALID_PARAMETER; + + mac->FramesPerPacket = FramesPerPacket; + mac->format = *format; + WLog_INFO(TAG, "Audio Format %s [channels=%d, samples=%d, bits=%d]", + audio_format_get_tag_string(format->wFormatTag), format->nChannels, + format->nSamplesPerSec, format->wBitsPerSample); + mac->audioFormat.mBitsPerChannel = format->wBitsPerSample; + + if (format->wBitsPerSample == 0) + mac->audioFormat.mBitsPerChannel = 16; + + mac->audioFormat.mBytesPerFrame = 0; + mac->audioFormat.mBytesPerPacket = 0; + mac->audioFormat.mChannelsPerFrame = mac->format.nChannels; + mac->audioFormat.mFormatFlags = audin_mac_get_flags_for_format(format); + mac->audioFormat.mFormatID = audin_mac_get_format(format); + mac->audioFormat.mFramesPerPacket = 1; + mac->audioFormat.mReserved = 0; + mac->audioFormat.mSampleRate = mac->format.nSamplesPerSec; + 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) +{ + AudinMacDevice *mac = (AudinMacDevice *)aqData; + UINT error = CHANNEL_RC_OK; + const BYTE *buffer = inBuffer->mAudioData; + int buffer_size = inBuffer->mAudioDataByteSize; + (void)inAQ; + (void)inStartTime; + (void)inNumPackets; + (void)inPacketDesc; + + if (buffer_size > 0) + error = mac->receive(&mac->format, buffer, buffer_size, mac->user_data); + + AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL); + + if (error) + { + WLog_ERR(TAG, "mac->receive failed with error %" PRIu32 "", error); + SetLastError(ERROR_INTERNAL_ERROR); + } +} + +static UINT audin_mac_close(IAudinDevice *device) +{ + UINT errCode = CHANNEL_RC_OK; + char errString[1024]; + OSStatus devStat; + AudinMacDevice *mac = (AudinMacDevice *)device; + + if (!mac->isAuthorized) + return ERROR_INTERNAL_ERROR; + + if (device == NULL) + return ERROR_INVALID_PARAMETER; + + if (mac->isOpen) + { + devStat = AudioQueueStop(mac->audioQueue, true); + + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueStop failed with %s [%" PRIu32 "]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + } + + mac->isOpen = false; + } + + if (mac->audioQueue) + { + devStat = AudioQueueDispose(mac->audioQueue, true); + + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueDispose failed with %s [%" PRIu32 "]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + } + + mac->audioQueue = NULL; + } + + mac->receive = NULL; + mac->user_data = NULL; + return errCode; +} + +static UINT audin_mac_open(IAudinDevice *device, AudinReceive receive, void *user_data) +{ + 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, + kCFRunLoopCommonModes, 0, &(mac->audioQueue)); + + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueNewInput failed with %s [%" PRIu32 "]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + goto err_out; + } + + for (index = 0; index < MAC_AUDIO_QUEUE_NUM_BUFFERS; index++) + { + devStat = AudioQueueAllocateBuffer(mac->audioQueue, + mac->FramesPerPacket * 2 * mac->format.nChannels, + &mac->audioBuffers[index]); + + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueAllocateBuffer failed with %s [%" PRIu32 "]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + goto err_out; + } + + devStat = AudioQueueEnqueueBuffer(mac->audioQueue, mac->audioBuffers[index], 0, NULL); + + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueEnqueueBuffer failed with %s [%" PRIu32 "]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + goto err_out; + } + } + + devStat = AudioQueueStart(mac->audioQueue, NULL); + + if (devStat != 0) + { + errCode = GetLastError(); + WLog_ERR(TAG, "AudioQueueStart failed with %s [%" PRIu32 "]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + goto err_out; + } + + mac->isOpen = true; + return CHANNEL_RC_OK; +err_out: + audin_mac_close(device); + return CHANNEL_RC_INITIALIZATION_ERROR; +} + +static UINT audin_mac_free(IAudinDevice *device) +{ + AudinMacDevice *mac = (AudinMacDevice *)device; + int error; + + if (device == NULL) + return ERROR_INVALID_PARAMETER; + + if ((error = audin_mac_close(device))) + { + WLog_ERR(TAG, "audin_oss_close failed with error code %d!", error); + } + + free(mac); + return CHANNEL_RC_OK; +} + +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 audin_mac_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "", + NULL, NULL, -1, NULL, "audio device name" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; + + AudinMacDevice *mac = (AudinMacDevice *)device; + + if (args->argc == 1) + return CHANNEL_RC_OK; + + flags = + COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + status = + CommandLineParseArgumentsA(args->argc, args->argv, audin_mac_args, flags, mac, NULL, NULL); + + if (status < 0) + return ERROR_INVALID_PARAMETER; + + arg = audin_mac_args; + + do + { + if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) + continue; + + CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dev") + { + str_num = _strdup(arg->Value); + + if (!str_num) + { + errCode = GetLastError(); + WLog_ERR(TAG, "_strdup failed with %s [%d]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + return CHANNEL_RC_NO_MEMORY; + } + + mac->dev_unit = strtol(str_num, &eptr, 10); + + if (mac->dev_unit < 0 || *eptr != '\0') + mac->dev_unit = -1; + + free(str_num); + } + CommandLineSwitchEnd(arg) + } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + + return CHANNEL_RC_OK; +} + +#ifdef BUILTIN_CHANNELS +#define freerdp_audin_client_subsystem_entry mac_freerdp_audin_client_subsystem_entry +#else +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry +#endif + +UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) +{ + DWORD errCode; + char errString[1024]; + ADDIN_ARGV *args; + AudinMacDevice *mac; + UINT error; + mac = (AudinMacDevice *)calloc(1, sizeof(AudinMacDevice)); + + if (!mac) + { + errCode = GetLastError(); + WLog_ERR(TAG, "calloc failed with %s [%" PRIu32 "]", + winpr_strerror(errCode, errString, sizeof(errString)), errCode); + return CHANNEL_RC_NO_MEMORY; + } + + mac->iface.Open = audin_mac_open; + mac->iface.FormatSupported = audin_mac_format_supported; + mac->iface.SetFormat = audin_mac_set_format; + mac->iface.Close = audin_mac_close; + mac->iface.Free = audin_mac_free; + mac->rdpcontext = pEntryPoints->rdpcontext; + mac->dev_unit = -1; + args = pEntryPoints->args; + + if ((error = audin_mac_parse_addin_args(mac, args))) + { + WLog_ERR(TAG, "audin_mac_parse_addin_args failed with %" PRIu32 "!", error); + goto error_out; + } + + 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); + return error; +} diff -Nru freerdp2-2.2.0+dfsg1/channels/audin/client/mac/CMakeLists.txt freerdp2-2.3.0+dfsg1/channels/audin/client/mac/CMakeLists.txt --- freerdp2-2.2.0+dfsg1/channels/audin/client/mac/CMakeLists.txt 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/audin/client/mac/CMakeLists.txt 2021-02-25 08:51:41.000000000 +0000 @@ -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}) diff -Nru freerdp2-2.2.0+dfsg1/channels/audin/server/audin.c freerdp2-2.3.0+dfsg1/channels/audin/server/audin.c --- freerdp2-2.2.0+dfsg1/channels/audin/server/audin.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/audin/server/audin.c 2021-02-25 08:51:41.000000000 +0000 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -567,8 +568,8 @@ 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) { diff -Nru freerdp2-2.2.0+dfsg1/channels/cliprdr/client/cliprdr_format.c freerdp2-2.3.0+dfsg1/channels/cliprdr/client/cliprdr_format.c --- freerdp2-2.2.0+dfsg1/channels/cliprdr/client/cliprdr_format.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/cliprdr/client/cliprdr_format.c 2021-02-25 08:51:41.000000000 +0000 @@ -206,7 +206,7 @@ * @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 @@ } *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 @@ { 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,10 +288,18 @@ * * @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; wStream* s = NULL; @@ -299,6 +307,12 @@ 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 @@ { 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 @@ * * 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) */ diff -Nru freerdp2-2.2.0+dfsg1/channels/cliprdr/client/cliprdr_main.c freerdp2-2.3.0+dfsg1/channels/cliprdr/client/cliprdr_main.c --- freerdp2-2.2.0+dfsg1/channels/cliprdr/client/cliprdr_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/cliprdr/client/cliprdr_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -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 @@ 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 @@ 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 @@ #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 @@ 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 @@ 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) diff -Nru freerdp2-2.2.0+dfsg1/channels/cliprdr/client/cliprdr_main.h freerdp2-2.3.0+dfsg1/channels/cliprdr/client/cliprdr_main.h --- freerdp2-2.2.0+dfsg1/channels/cliprdr/client/cliprdr_main.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/cliprdr/client/cliprdr_main.h 2021-02-25 08:51:41.000000000 +0000 @@ -49,6 +49,7 @@ BOOL streamFileClipEnabled; BOOL fileClipNoFilePaths; BOOL canLockClipData; + BOOL hasHugeFileSupport; }; typedef struct cliprdr_plugin cliprdrPlugin; diff -Nru freerdp2-2.2.0+dfsg1/channels/cliprdr/cliprdr_common.c freerdp2-2.3.0+dfsg1/channels/cliprdr/cliprdr_common.c --- freerdp2-2.2.0+dfsg1/channels/cliprdr/cliprdr_common.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/cliprdr/cliprdr_common.c 2021-02-25 08:51:41.000000000 +0000 @@ -191,6 +191,7 @@ 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 @@ 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 @@ 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 @@ } else { - UINT32 length = 0; + length = 0; for (index = 0; index < formatList->numFormats; index++) { format = (CLIPRDR_FORMAT*)&(formatList->formats[index]); @@ -290,7 +294,10 @@ 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 @@ lpWideCharStr, cchWideChar) * 2; if (formatNameSize < 0) + { + Stream_Free(s, TRUE); return NULL; + } Stream_Seek(s, (size_t)formatNameSize); } else diff -Nru freerdp2-2.2.0+dfsg1/channels/cliprdr/server/cliprdr_main.c freerdp2-2.3.0+dfsg1/channels/cliprdr/server/cliprdr_main.c --- freerdp2-2.2.0+dfsg1/channels/cliprdr/server/cliprdr_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/cliprdr/server/cliprdr_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -453,6 +453,10 @@ 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 @@ 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 @@ 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; diff -Nru freerdp2-2.2.0+dfsg1/channels/disp/client/disp_main.c freerdp2-2.3.0+dfsg1/channels/disp/client/disp_main.c --- freerdp2-2.2.0+dfsg1/channels/disp/client/disp_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/disp/client/disp_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -72,6 +72,7 @@ UINT32 MaxNumMonitors; UINT32 MaxMonitorAreaFactorA; UINT32 MaxMonitorAreaFactorB; + BOOL initialized; }; typedef struct _DISP_PLUGIN DISP_PLUGIN; @@ -296,6 +297,11 @@ { 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 @@ 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; } diff -Nru freerdp2-2.2.0+dfsg1/channels/drdynvc/client/drdynvc_main.c freerdp2-2.3.0+dfsg1/channels/drdynvc/client/drdynvc_main.c --- freerdp2-2.2.0+dfsg1/channels/drdynvc/client/drdynvc_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/drdynvc/client/drdynvc_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -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 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 @@ 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 @@ 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_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 @@ * * @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 @@ * @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 @@ 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 @@ /* 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_attached(drdynvcPlugin* drdynvc) { UINT error = CHANNEL_RC_OK; - size_t i; + int i; DVCMAN* dvcman; if (!drdynvc) @@ -1638,7 +1653,7 @@ static UINT drdynvc_virtual_channel_event_detached(drdynvcPlugin* drdynvc) { UINT error = CHANNEL_RC_OK; - size_t i; + int i; DVCMAN* dvcman; if (!drdynvc) diff -Nru freerdp2-2.2.0+dfsg1/channels/echo/client/echo_main.c freerdp2-2.3.0+dfsg1/channels/echo/client/echo_main.c --- freerdp2-2.2.0+dfsg1/channels/echo/client/echo_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/echo/client/echo_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -31,6 +31,7 @@ #include "echo_main.h" #include +#include #define TAG CHANNELS_TAG("echo.client") @@ -60,6 +61,7 @@ ECHO_LISTENER_CALLBACK* listener_callback; IWTSListener* listener; + BOOL initialized; }; /** @@ -129,8 +131,13 @@ */ 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 @@ 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; } /** diff -Nru freerdp2-2.2.0+dfsg1/channels/geometry/client/geometry_main.c freerdp2-2.3.0+dfsg1/channels/geometry/client/geometry_main.c --- freerdp2-2.2.0+dfsg1/channels/geometry/client/geometry_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/geometry/client/geometry_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -68,6 +68,7 @@ GEOMETRY_LISTENER_CALLBACK* listener_callback; GeometryClientContext* context; + BOOL initialized; }; typedef struct _GEOMETRY_PLUGIN GEOMETRY_PLUGIN; @@ -380,6 +381,11 @@ { 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 @@ 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; } diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpdr/client/rdpdr_main.c freerdp2-2.3.0+dfsg1/channels/rdpdr/client/rdpdr_main.c --- freerdp2-2.2.0+dfsg1/channels/rdpdr/client/rdpdr_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpdr/client/rdpdr_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -580,14 +580,6 @@ #else -#include -#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,46 +637,160 @@ return FALSE; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT handle_hotplug(rdpdrPlugin* rdpdr) +#define MAX_USB_DEVICES 100 + +typedef struct _hotplug_dev { - 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; + char* path; + BOOL to_add; +} hotplug_dev; - f = fopen("/proc/mounts", "r"); +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 +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 +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 +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) { - /* Copy the line, path must obviously be shorter */ - const char* path = ent->mnt_dir; - if (!path) + 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; - /* copy hotpluged device mount point to the dev_array */ - if (isAutomountLocation(path) && (size < MAX_USB_DEVICES)) + if (_wcscmp(device_ext->path, path) == 0) { - dev_array[size].path = _strdup(path); - dev_array[size++].to_add = TRUE; + rc = TRUE; + break; } } + free(keys); + free(path); + ListDictionary_Unlock(rdpdr->devman->devices); + return rc; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT handle_hotplug(rdpdrPlugin* rdpdr) +{ + hotplug_dev dev_array[MAX_USB_DEVICES] = { 0 }; + size_t i; + size_t size = 0; + int count, j; + ULONG_PTR* keys = NULL; + UINT32 ids[1]; + UINT error = ERROR_SUCCESS; + + error = handle_platform_mounts(dev_array, &size); - fclose(f); /* delete removed devices */ count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys); @@ -738,7 +844,7 @@ /* 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; diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpei/client/rdpei_main.c freerdp2-2.3.0+dfsg1/channels/rdpei/client/rdpei_main.c --- freerdp2-2.2.0+dfsg1/channels/rdpei/client/rdpei_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpei/client/rdpei_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -62,7 +62,8 @@ * http://msdn.microsoft.com/en-us/library/hh454910/ */ -#define MAX_CONTACTS 512 +#define MAX_CONTACTS 64 +#define MAX_PEN_CONTACTS 4 struct _RDPEI_CHANNEL_CALLBACK { @@ -93,15 +94,23 @@ RdpeiClientContext* context; - int version; + UINT32 version; + UINT32 features; UINT16 maxTouchContacts; UINT64 currentFrameTime; UINT64 previousFrameTime; - RDPINPUT_TOUCH_FRAME frame; - RDPINPUT_CONTACT_DATA contacts[MAX_CONTACTS]; - RDPINPUT_CONTACT_POINT* contactPoints; + RDPINPUT_CONTACT_POINT contactPoints[MAX_CONTACTS]; + UINT64 currentPenFrameTime; + UINT64 previousPenFrameTime; + UINT16 maxPenContacts; + RDPINPUT_PEN_CONTACT_POINT penContactPoints[MAX_PEN_CONTACTS]; + + CRITICAL_SECTION lock; rdpContext* rdpcontext; + BOOL initialized; + HANDLE thread; + HANDLE event; }; typedef struct _RDPEI_PLUGIN RDPEI_PLUGIN; @@ -110,7 +119,7 @@ * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpei_send_frame(RdpeiClientContext* context); +static UINT rdpei_send_frame(RdpeiClientContext* context, RDPINPUT_TOUCH_FRAME* frame); #ifdef WITH_DEBUG_RDPEI static const char* rdpei_eventid_string(UINT16 event) @@ -129,12 +138,39 @@ return "EVENTID_RESUME_TOUCH"; case EVENTID_DISMISS_HOVERING_CONTACT: return "EVENTID_DISMISS_HOVERING_CONTACT"; + case EVENTID_PEN: + return "EVENTID_PEN"; default: return "EVENTID_UNKNOWN"; } } #endif +static RDPINPUT_CONTACT_POINT* rdpei_contact(RDPEI_PLUGIN* rdpei, INT32 externalId, BOOL active) +{ + UINT16 i; + + for (i = 0; i < rdpei->maxTouchContacts; i++) + { + RDPINPUT_CONTACT_POINT* contactPoint = &rdpei->contactPoints[i]; + + if (!contactPoint->active && active) + continue; + else if (!contactPoint->active && !active) + { + contactPoint->contactId = i; + contactPoint->externalId = externalId; + contactPoint->active = TRUE; + return contactPoint; + } + else if (contactPoint->externalId == externalId) + { + return contactPoint; + } + } + return NULL; +} + /** * Function description * @@ -142,23 +178,29 @@ */ static UINT rdpei_add_frame(RdpeiClientContext* context) { - int i; - RDPINPUT_CONTACT_DATA* contact; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; - rdpei->frame.contactCount = 0; + UINT16 i; + RDPEI_PLUGIN* rdpei; + RDPINPUT_TOUCH_FRAME frame = { 0 }; + RDPINPUT_CONTACT_DATA contacts[MAX_CONTACTS] = { 0 }; + + if (!context || !context->handle) + return ERROR_INTERNAL_ERROR; + + rdpei = (RDPEI_PLUGIN*)context->handle; + frame.contacts = contacts; for (i = 0; i < rdpei->maxTouchContacts; i++) { - contact = (RDPINPUT_CONTACT_DATA*)&(rdpei->contactPoints[i].data); + RDPINPUT_CONTACT_POINT* contactPoint = &rdpei->contactPoints[i]; + RDPINPUT_CONTACT_DATA* contact = &contactPoint->data; - if (rdpei->contactPoints[i].dirty) + if (contactPoint->dirty) { - CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact, - sizeof(RDPINPUT_CONTACT_DATA)); + contacts[frame.contactCount] = *contact; rdpei->contactPoints[i].dirty = FALSE; - rdpei->frame.contactCount++; + frame.contactCount++; } - else if (rdpei->contactPoints[i].active) + else if (contactPoint->active) { if (contact->contactFlags & CONTACT_FLAG_DOWN) { @@ -167,12 +209,26 @@ contact->contactFlags |= CONTACT_FLAG_INCONTACT; } - CopyMemory(&(rdpei->contacts[rdpei->frame.contactCount]), contact, - sizeof(RDPINPUT_CONTACT_DATA)); - rdpei->frame.contactCount++; + contacts[frame.contactCount] = *contact; + frame.contactCount++; + } + if (contact->contactFlags & CONTACT_FLAG_UP) + { + contactPoint->active = FALSE; + contactPoint->externalId = 0; + contactPoint->contactId = 0; } } + if (frame.contactCount > 0) + { + UINT error = rdpei_send_frame(context, &frame); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "rdpei_send_frame failed with error %" PRIu32 "!", error); + return error; + } + } return CHANNEL_RC_OK; } @@ -185,6 +241,9 @@ UINT32 pduLength) { UINT status; + if (!callback || !s || !callback->channel || !callback->channel->Write) + return ERROR_INTERNAL_ERROR; + Stream_SetPosition(s, 0); Stream_Write_UINT16(s, eventId); /* eventId (2 bytes) */ Stream_Write_UINT32(s, pduLength); /* pduLength (4 bytes) */ @@ -199,6 +258,249 @@ return status; } +static UINT rdpei_write_pen_frame(wStream* s, const RDPINPUT_PEN_FRAME* frame) +{ + UINT16 x; + if (!s || !frame) + return ERROR_INTERNAL_ERROR; + + if (!rdpei_write_2byte_unsigned(s, frame->contactCount)) + return ERROR_OUTOFMEMORY; + if (!rdpei_write_8byte_unsigned(s, frame->frameOffset)) + return ERROR_OUTOFMEMORY; + for (x = 0; x < frame->contactCount; x++) + { + const RDPINPUT_PEN_CONTACT* contact = &frame->contacts[x]; + + if (!Stream_EnsureRemainingCapacity(s, 1)) + return ERROR_OUTOFMEMORY; + Stream_Write_UINT8(s, contact->deviceId); + if (!rdpei_write_2byte_unsigned(s, contact->fieldsPresent)) + return ERROR_OUTOFMEMORY; + if (!rdpei_write_4byte_signed(s, contact->x)) + return ERROR_OUTOFMEMORY; + if (!rdpei_write_4byte_signed(s, contact->y)) + return ERROR_OUTOFMEMORY; + if (!rdpei_write_4byte_unsigned(s, contact->contactFlags)) + return ERROR_OUTOFMEMORY; + if (contact->fieldsPresent & PEN_CONTACT_PENFLAGS_PRESENT) + { + if (!rdpei_write_4byte_unsigned(s, contact->penFlags)) + return ERROR_OUTOFMEMORY; + } + if (contact->fieldsPresent & PEN_CONTACT_PRESSURE_PRESENT) + { + if (!rdpei_write_4byte_unsigned(s, contact->pressure)) + return ERROR_OUTOFMEMORY; + } + if (contact->fieldsPresent & PEN_CONTACT_ROTATION_PRESENT) + { + if (!rdpei_write_2byte_unsigned(s, contact->rotation)) + return ERROR_OUTOFMEMORY; + } + if (contact->fieldsPresent & PEN_CONTACT_TILTX_PRESENT) + { + if (!rdpei_write_2byte_signed(s, contact->tiltX)) + return ERROR_OUTOFMEMORY; + } + if (contact->fieldsPresent & PEN_CONTACT_TILTY_PRESENT) + { + if (!rdpei_write_2byte_signed(s, contact->tiltY)) + return ERROR_OUTOFMEMORY; + } + } + return CHANNEL_RC_OK; +} + +static UINT rdpei_send_pen_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, UINT32 frameOffset, + const RDPINPUT_PEN_FRAME* frames, UINT16 count) +{ + UINT status; + wStream* s; + UINT16 x; + + if (!frames || (count == 0)) + return ERROR_INTERNAL_ERROR; + + s = Stream_New(NULL, 64); + + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + Stream_Seek(s, RDPINPUT_HEADER_LENGTH); + /** + * the time that has elapsed (in milliseconds) from when the oldest touch frame + * was generated to when it was encoded for transmission by the client. + */ + rdpei_write_4byte_unsigned(s, frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */ + rdpei_write_2byte_unsigned(s, count); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */ + + for (x = 0; x < count; x++) + { + if ((status = rdpei_write_pen_frame(s, &frames[x]))) + { + WLog_ERR(TAG, "rdpei_write_touch_frame failed with error %" PRIu32 "!", status); + Stream_Free(s, TRUE); + return status; + } + } + Stream_SealLength(s); + + status = rdpei_send_pdu(callback, s, EVENTID_PEN, Stream_Length(s)); + Stream_Free(s, TRUE); + return status; +} + +static UINT rdpei_send_pen_frame(RdpeiClientContext* context, RDPINPUT_PEN_FRAME* frame) +{ + const UINT64 currentTime = GetTickCount64(); + RDPEI_PLUGIN* rdpei; + RDPEI_CHANNEL_CALLBACK* callback; + UINT error; + + if (!context) + return ERROR_INTERNAL_ERROR; + rdpei = (RDPEI_PLUGIN*)context->handle; + if (!rdpei || !rdpei->listener_callback) + return ERROR_INTERNAL_ERROR; + + callback = rdpei->listener_callback->channel_callback; + + if (!rdpei->previousPenFrameTime && !rdpei->currentPenFrameTime) + { + rdpei->currentPenFrameTime = currentTime; + frame->frameOffset = 0; + } + else + { + rdpei->currentPenFrameTime = currentTime; + frame->frameOffset = rdpei->currentPenFrameTime - rdpei->previousPenFrameTime; + } + + if ((error = rdpei_send_pen_event_pdu(callback, frame->frameOffset, frame, 1))) + return error; + + rdpei->previousPenFrameTime = rdpei->currentPenFrameTime; + return error; +} + +static UINT rdpei_add_pen_frame(RdpeiClientContext* context) +{ + UINT16 i; + RDPEI_PLUGIN* rdpei; + RDPINPUT_PEN_FRAME penFrame = { 0 }; + RDPINPUT_PEN_CONTACT penContacts[MAX_PEN_CONTACTS] = { 0 }; + + if (!context || !context->handle) + return ERROR_INTERNAL_ERROR; + + rdpei = (RDPEI_PLUGIN*)context->handle; + + penFrame.contacts = penContacts; + + for (i = 0; i < rdpei->maxPenContacts; i++) + { + RDPINPUT_PEN_CONTACT_POINT* contact = &(rdpei->penContactPoints[i]); + + if (contact->dirty) + { + penContacts[penFrame.contactCount++] = contact->data; + contact->dirty = FALSE; + } + else if (contact->active) + { + if (contact->data.contactFlags & CONTACT_FLAG_DOWN) + { + contact->data.contactFlags = CONTACT_FLAG_UPDATE; + contact->data.contactFlags |= CONTACT_FLAG_INRANGE; + contact->data.contactFlags |= CONTACT_FLAG_INCONTACT; + } + + penContacts[penFrame.contactCount++] = contact->data; + } + if (contact->data.contactFlags & CONTACT_FLAG_UP) + { + contact->externalId = 0; + contact->active = FALSE; + } + } + + if (penFrame.contactCount > 0) + return rdpei_send_pen_frame(context, &penFrame); + return CHANNEL_RC_OK; +} + +static UINT rdpei_update(RdpeiClientContext* context) +{ + UINT error = rdpei_add_frame(context); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "rdpei_add_frame failed with error %" PRIu32 "!", error); + return error; + } + + return rdpei_add_pen_frame(context); +} + +static DWORD WINAPI rdpei_periodic_update(LPVOID arg) +{ + DWORD status; + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)arg; + UINT error = CHANNEL_RC_OK; + RdpeiClientContext* context; + + if (!rdpei) + { + error = ERROR_INVALID_PARAMETER; + goto out; + } + + context = (RdpeiClientContext*)rdpei->iface.pInterface; + + if (!context) + { + error = ERROR_INVALID_PARAMETER; + goto out; + } + + while (rdpei->initialized) + { + status = WaitForSingleObject(rdpei->event, 20); + + if (status == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "!", error); + break; + } + + EnterCriticalSection(&rdpei->lock); + + error = rdpei_update(context); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "rdpei_add_frame failed with error %" PRIu32 "!", error); + break; + } + + if (status == WAIT_OBJECT_0) + ResetEvent(rdpei->event); + + LeaveCriticalSection(&rdpei->lock); + } + +out: + + if (error && rdpei && rdpei->rdpcontext) + setChannelError(rdpei->rdpcontext, error, "rdpei_schedule_thread reported an error"); + + ExitThread(error); + return error; +} + /** * Function description * @@ -210,10 +512,17 @@ wStream* s; UINT32 flags; UINT32 pduLength; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)callback->plugin; + RDPEI_PLUGIN* rdpei; + + if (!callback || !callback->plugin) + return ERROR_INTERNAL_ERROR; + + rdpei = (RDPEI_PLUGIN*)callback->plugin; flags = 0; - flags |= READY_FLAGS_SHOW_TOUCH_VISUALS; - // flags |= READY_FLAGS_DISABLE_TIMESTAMP_INJECTION; + flags |= CS_READY_FLAGS_SHOW_TOUCH_VISUALS; + if (rdpei->version > RDPINPUT_PROTOCOL_V10) + flags |= CS_READY_FLAGS_DISABLE_TIMESTAMP_INJECTION; + flags |= CS_READY_FLAGS_ENABLE_MULTIPEN_INJECTION; pduLength = RDPINPUT_HEADER_LENGTH + 10; s = Stream_New(NULL, pduLength); @@ -225,7 +534,7 @@ Stream_Seek(s, RDPINPUT_HEADER_LENGTH); Stream_Write_UINT32(s, flags); /* flags (4 bytes) */ - Stream_Write_UINT32(s, RDPINPUT_PROTOCOL_V10); /* protocolVersion (4 bytes) */ + Stream_Write_UINT32(s, rdpei->version); /* protocolVersion (4 bytes) */ Stream_Write_UINT16(s, rdpei->maxTouchContacts); /* maxTouchContacts (2 bytes) */ Stream_SealLength(s); status = rdpei_send_pdu(callback, s, EVENTID_CS_READY, pduLength); @@ -264,6 +573,8 @@ UINT32 index; int rectSize = 2; RDPINPUT_CONTACT_DATA* contact; + if (!s || !frame) + return ERROR_INTERNAL_ERROR; #ifdef WITH_DEBUG_RDPEI WLog_DBG(TAG, "contactCount: %" PRIu32 "", frame->contactCount); WLog_DBG(TAG, "frameOffset: 0x%016" PRIX64 "", frame->frameOffset); @@ -348,6 +659,8 @@ UINT status; wStream* s; UINT32 pduLength; + if (!frame) + return ERROR_INTERNAL_ERROR; pduLength = 64 + (frame->contactCount * 64); s = Stream_New(NULL, pduLength); @@ -387,8 +700,32 @@ */ static UINT rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) { + UINT32 features = 0; + UINT32 size; UINT32 protocolVersion; + RDPEI_PLUGIN* rdpei; + + if (!callback || !callback->plugin) + return ERROR_INTERNAL_ERROR; + + rdpei = (RDPEI_PLUGIN*)callback->plugin; + + size = Stream_GetRemainingLength(s); + if (size < 4) + return ERROR_INVALID_DATA; Stream_Read_UINT32(s, protocolVersion); /* protocolVersion (4 bytes) */ + + if (protocolVersion >= RDPINPUT_PROTOCOL_V300) + { + if (size < 8) + return ERROR_INVALID_DATA; + } + if (size >= 9) + Stream_Read_UINT32(s, features); + + if (rdpei->version > protocolVersion) + rdpei->version = protocolVersion; + rdpei->features = features; #if 0 if (protocolVersion != RDPINPUT_PROTOCOL_V10) @@ -408,8 +745,17 @@ */ static UINT rdpei_recv_suspend_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) { - RdpeiClientContext* rdpei = (RdpeiClientContext*)callback->plugin->pInterface; UINT error = CHANNEL_RC_OK; + RdpeiClientContext* rdpei; + + WINPR_UNUSED(s); + + if (!callback || !callback->plugin) + return ERROR_INTERNAL_ERROR; + rdpei = (RdpeiClientContext*)callback->plugin->pInterface; + if (!rdpei) + return ERROR_INTERNAL_ERROR; + IFCALLRET(rdpei->SuspendTouch, error, rdpei); if (error) @@ -425,8 +771,14 @@ */ static UINT rdpei_recv_resume_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) { - RdpeiClientContext* rdpei = (RdpeiClientContext*)callback->plugin->pInterface; + RdpeiClientContext* rdpei; UINT error = CHANNEL_RC_OK; + if (!s || !callback || !callback->plugin) + return ERROR_INTERNAL_ERROR; + rdpei = (RdpeiClientContext*)callback->plugin->pInterface; + if (!rdpei) + return ERROR_INTERNAL_ERROR; + IFCALLRET(rdpei->ResumeTouch, error, rdpei); if (error) @@ -445,6 +797,8 @@ UINT16 eventId; UINT32 pduLength; UINT error; + if (!s) + return ERROR_INTERNAL_ERROR; if (Stream_GetRemainingLength(s) < 6) return ERROR_INVALID_DATA; @@ -531,8 +885,13 @@ { RDPEI_CHANNEL_CALLBACK* callback; RDPEI_LISTENER_CALLBACK* listener_callback = (RDPEI_LISTENER_CALLBACK*)pListenerCallback; + if (!listener_callback) + return ERROR_INTERNAL_ERROR; callback = (RDPEI_CHANNEL_CALLBACK*)calloc(1, sizeof(RDPEI_CHANNEL_CALLBACK)); + WINPR_UNUSED(Data); + WINPR_UNUSED(pbAccept); + if (!callback) { WLog_ERR(TAG, "calloc failed!"); @@ -554,10 +913,53 @@ * * @return 0 on success, otherwise a Win32 error code */ +static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin) +{ + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)pPlugin; + + if (!pPlugin) + return ERROR_INVALID_PARAMETER; + + if (rdpei && rdpei->listener_callback) + { + IWTSVirtualChannelManager* mgr = rdpei->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, rdpei->listener); + + rdpei->initialized = FALSE; + if (rdpei->event) + SetEvent(rdpei->event); + + if (rdpei->thread) + { + WaitForSingleObject(rdpei->thread, INFINITE); + CloseHandle(rdpei->thread); + } + if (rdpei->event) + CloseHandle(rdpei->event); + } + DeleteCriticalSection(&rdpei->lock); + free(rdpei->listener_callback); + free(rdpei->context); + free(rdpei); + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { UINT error; RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)pPlugin; + + if (rdpei->initialized) + { + WLog_ERR(TAG, "[%s] channel initialized twice, aborting", RDPEI_DVC_CHANNEL_NAME); + return ERROR_INVALID_DATA; + } rdpei->listener_callback = (RDPEI_LISTENER_CALLBACK*)calloc(1, sizeof(RDPEI_LISTENER_CALLBACK)); if (!rdpei->listener_callback) @@ -579,53 +981,48 @@ rdpei->listener->pInterface = rdpei->iface.pInterface; + InitializeCriticalSection(&rdpei->lock); + rdpei->event = CreateEventA(NULL, TRUE, FALSE, NULL); + if (!rdpei->event) + goto error_out; + rdpei->thread = CreateThread(NULL, 0, rdpei_periodic_update, rdpei, 0, NULL); + if (!rdpei->thread) + goto error_out; + rdpei->initialized = TRUE; return error; error_out: - free(rdpei->listener_callback); + rdpei_plugin_terminated(pPlugin); return error; } /** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin) -{ - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)pPlugin; - - if (!pPlugin) - return ERROR_INVALID_PARAMETER; - - if (rdpei && rdpei->listener_callback) - { - IWTSVirtualChannelManager* mgr = rdpei->listener_callback->channel_mgr; - if (mgr) - IFCALL(mgr->DestroyListener, mgr, rdpei->listener); - } - free(rdpei->listener_callback); - free(rdpei->contactPoints); - free(rdpei->context); - free(rdpei); - return CHANNEL_RC_OK; -} - -/** * Channel Client Interface */ -static int rdpei_get_version(RdpeiClientContext* context) +static UINT32 rdpei_get_version(RdpeiClientContext* context) { - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; + RDPEI_PLUGIN* rdpei; + if (!context || !context->handle) + return -1; + rdpei = (RDPEI_PLUGIN*)context->handle; return rdpei->version; } +static UINT32 rdpei_get_features(RdpeiClientContext* context) +{ + RDPEI_PLUGIN* rdpei; + if (!context || !context->handle) + return -1; + rdpei = (RDPEI_PLUGIN*)context->handle; + return rdpei->features; +} + /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_send_frame(RdpeiClientContext* context) +UINT rdpei_send_frame(RdpeiClientContext* context, RDPINPUT_TOUCH_FRAME* frame) { UINT64 currentTime; RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; @@ -636,22 +1033,21 @@ if (!rdpei->previousFrameTime && !rdpei->currentFrameTime) { rdpei->currentFrameTime = currentTime; - rdpei->frame.frameOffset = 0; + frame->frameOffset = 0; } else { rdpei->currentFrameTime = currentTime; - rdpei->frame.frameOffset = rdpei->currentFrameTime - rdpei->previousFrameTime; + frame->frameOffset = rdpei->currentFrameTime - rdpei->previousFrameTime; } - if ((error = rdpei_send_touch_event_pdu(callback, &rdpei->frame))) + if ((error = rdpei_send_touch_event_pdu(callback, frame))) { WLog_ERR(TAG, "rdpei_send_touch_event_pdu failed with error %" PRIu32 "!", error); return error; } rdpei->previousFrameTime = rdpei->currentFrameTime; - rdpei->frame.contactCount = 0; return error; } @@ -662,127 +1058,195 @@ */ static UINT rdpei_add_contact(RdpeiClientContext* context, const RDPINPUT_CONTACT_DATA* contact) { - UINT error; RDPINPUT_CONTACT_POINT* contactPoint; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; - - contactPoint = (RDPINPUT_CONTACT_POINT*)&rdpei->contactPoints[contact->contactId]; - CopyMemory(&(contactPoint->data), contact, sizeof(RDPINPUT_CONTACT_DATA)); + RDPEI_PLUGIN* rdpei; + if (!context || !contact || !context->handle) + return ERROR_INTERNAL_ERROR; + + rdpei = (RDPEI_PLUGIN*)context->handle; + + EnterCriticalSection(&rdpei->lock); + contactPoint = &rdpei->contactPoints[contact->contactId]; + contactPoint->data = *contact; contactPoint->dirty = TRUE; + SetEvent(rdpei->event); + LeaveCriticalSection(&rdpei->lock); - error = rdpei_add_frame(context); - if (error != CHANNEL_RC_OK) - { - WLog_ERR(TAG, "rdpei_add_frame failed with error %" PRIu32 "!", error); - return error; - } - - if (rdpei->frame.contactCount > 0) - { - error = rdpei_send_frame(context); - if (error != CHANNEL_RC_OK) - { - WLog_ERR(TAG, "rdpei_send_frame failed with error %" PRIu32 "!", error); - return error; - } - } return CHANNEL_RC_OK; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y, - int* contactId) +static UINT rdpei_touch_process(RdpeiClientContext* context, INT32 externalId, UINT32 contactFlags, + INT32 x, INT32 y, INT32* contactId) { - unsigned int i; INT64 contactIdlocal = -1; - RDPINPUT_CONTACT_DATA contact; - RDPINPUT_CONTACT_POINT* contactPoint = NULL; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; + RDPINPUT_CONTACT_POINT* contactPoint; + RDPEI_PLUGIN* rdpei; + BOOL begin; UINT error = CHANNEL_RC_OK; - /* Create a new contact point in an empty slot */ - - for (i = 0; i < rdpei->maxTouchContacts; i++) - { - contactPoint = (RDPINPUT_CONTACT_POINT*)&rdpei->contactPoints[i]; + if (!context || !contactId || !context->handle) + return ERROR_INTERNAL_ERROR; - if (!contactPoint->active) - { - contactPoint->contactId = i; - contactIdlocal = contactPoint->contactId; - contactPoint->externalId = externalId; - contactPoint->active = TRUE; - contactPoint->state = RDPINPUT_CONTACT_STATE_ENGAGED; - break; - } - } + rdpei = (RDPEI_PLUGIN*)context->handle; + /* Create a new contact point in an empty slot */ + EnterCriticalSection(&rdpei->lock); + begin = contactFlags & CONTACT_FLAG_DOWN; + contactPoint = rdpei_contact(rdpei, externalId, !begin); + if (contactPoint) + contactIdlocal = contactPoint->contactId; + LeaveCriticalSection(&rdpei->lock); if (contactIdlocal >= 0) { - ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA)); - contactPoint->lastX = x; - contactPoint->lastY = y; + RDPINPUT_CONTACT_DATA contact = { 0 }; contact.x = x; contact.y = y; - contact.contactId = (UINT32)contactIdlocal; - contact.contactFlags |= CONTACT_FLAG_DOWN; - contact.contactFlags |= CONTACT_FLAG_INRANGE; - contact.contactFlags |= CONTACT_FLAG_INCONTACT; + contact.contactId = contactIdlocal; + contact.contactFlags = contactFlags; error = context->AddContact(context, &contact); } - *contactId = contactIdlocal; + if (contactId) + *contactId = contactIdlocal; return error; } +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rdpei_touch_begin(RdpeiClientContext* context, INT32 externalId, INT32 x, INT32 y, + INT32* contactId) +{ + return rdpei_touch_process(context, externalId, + CONTACT_FLAG_DOWN | CONTACT_FLAG_INRANGE | CONTACT_FLAG_INCONTACT, x, + y, contactId); +} /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int y, - int* contactId) +static UINT rdpei_touch_update(RdpeiClientContext* context, INT32 externalId, INT32 x, INT32 y, + INT32* contactId) { - unsigned int i; - int contactIdlocal = -1; - RDPINPUT_CONTACT_DATA contact; - RDPINPUT_CONTACT_POINT* contactPoint = NULL; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; - UINT error = CHANNEL_RC_OK; + return rdpei_touch_process(context, externalId, + CONTACT_FLAG_UPDATE | CONTACT_FLAG_INRANGE | CONTACT_FLAG_INCONTACT, + x, y, contactId); +} - for (i = 0; i < rdpei->maxTouchContacts; i++) - { - contactPoint = (RDPINPUT_CONTACT_POINT*)&rdpei->contactPoints[i]; +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rdpei_touch_end(RdpeiClientContext* context, INT32 externalId, INT32 x, INT32 y, + INT32* contactId) +{ + UINT error = rdpei_touch_process( + context, externalId, CONTACT_FLAG_UPDATE | CONTACT_FLAG_INRANGE | CONTACT_FLAG_INCONTACT, x, + y, contactId); + if (error != CHANNEL_RC_OK) + return error; + return rdpei_touch_process(context, externalId, CONTACT_FLAG_UP, x, y, contactId); +} - if (!contactPoint->active) - continue; +static RDPINPUT_PEN_CONTACT_POINT* rdpei_pen_contact(RDPEI_PLUGIN* rdpei, INT32 externalId, + BOOL active) +{ + UINT32 x; + if (!rdpei) + return NULL; - if (contactPoint->externalId == externalId) + for (x = 0; x < rdpei->maxPenContacts; x++) + { + RDPINPUT_PEN_CONTACT_POINT* contact = &rdpei->penContactPoints[x]; + if (active) { - contactIdlocal = contactPoint->contactId; - break; + if (contact->active) + { + if (contact->externalId == externalId) + return contact; + } + } + else + { + if (!contact->active) + { + contact->externalId = externalId; + contact->active = TRUE; + return contact; + } } } + return NULL; +} - if (contactIdlocal >= 0) +static UINT rdpei_add_pen(RdpeiClientContext* context, INT32 externalId, + const RDPINPUT_PEN_CONTACT* contact) +{ + RDPEI_PLUGIN* rdpei; + RDPINPUT_PEN_CONTACT_POINT* contactPoint; + + if (!context || !contact || !context->handle) + return ERROR_INTERNAL_ERROR; + + rdpei = (RDPEI_PLUGIN*)context->handle; + + EnterCriticalSection(&rdpei->lock); + contactPoint = rdpei_pen_contact(rdpei, externalId, TRUE); + if (contactPoint) { - ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA)); - contactPoint->lastX = x; - contactPoint->lastY = y; + contactPoint->data = *contact; + contactPoint->dirty = TRUE; + SetEvent(rdpei->event); + } + LeaveCriticalSection(&rdpei->lock); + + return CHANNEL_RC_OK; +} + +static UINT rdpei_pen_process(RdpeiClientContext* context, INT32 externalId, UINT32 contactFlags, + UINT32 fieldFlags, INT32 x, INT32 y, va_list ap) +{ + RDPINPUT_PEN_CONTACT_POINT* contactPoint; + RDPEI_PLUGIN* rdpei; + BOOL begin; + UINT error = CHANNEL_RC_OK; + + if (!context || !context->handle) + return ERROR_INTERNAL_ERROR; + + rdpei = (RDPEI_PLUGIN*)context->handle; + begin = contactFlags & CONTACT_FLAG_DOWN; + + EnterCriticalSection(&rdpei->lock); + contactPoint = rdpei_pen_contact(rdpei, externalId, !begin); + LeaveCriticalSection(&rdpei->lock); + if (contactPoint != NULL) + { + RDPINPUT_PEN_CONTACT contact = { 0 }; + contact.x = x; contact.y = y; - contact.contactId = (UINT32)contactIdlocal; - contact.contactFlags |= CONTACT_FLAG_UPDATE; - contact.contactFlags |= CONTACT_FLAG_INRANGE; - contact.contactFlags |= CONTACT_FLAG_INCONTACT; - error = context->AddContact(context, &contact); + contact.fieldsPresent = fieldFlags; + + contact.contactFlags = contactFlags; + if (fieldFlags & PEN_CONTACT_PENFLAGS_PRESENT) + contact.penFlags = va_arg(ap, UINT32); + if (fieldFlags & PEN_CONTACT_PRESSURE_PRESENT) + contact.pressure = va_arg(ap, UINT32); + if (fieldFlags & PEN_CONTACT_ROTATION_PRESENT) + contact.rotation = va_arg(ap, UINT32); + if (fieldFlags & PEN_CONTACT_TILTX_PRESENT) + contact.tiltX = va_arg(ap, INT32); + if (fieldFlags & PEN_CONTACT_TILTY_PRESENT) + contact.tiltY = va_arg(ap, INT32); + + error = context->AddPen(context, externalId, &contact); } - *contactId = contactIdlocal; return error; } @@ -791,64 +1255,59 @@ * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y, - int* contactId) +static UINT rdpei_pen_begin(RdpeiClientContext* context, INT32 externalId, UINT32 fieldFlags, + INT32 x, INT32 y, ...) { - unsigned int i; - int contactIdlocal = -1; - int tempvalue; - RDPINPUT_CONTACT_DATA contact; - RDPINPUT_CONTACT_POINT* contactPoint = NULL; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; UINT error; + va_list ap; - for (i = 0; i < rdpei->maxTouchContacts; i++) - { - contactPoint = (RDPINPUT_CONTACT_POINT*)&rdpei->contactPoints[i]; + va_start(ap, y); + error = rdpei_pen_process(context, externalId, + CONTACT_FLAG_DOWN | CONTACT_FLAG_INRANGE | CONTACT_FLAG_INCONTACT, + fieldFlags, x, y, ap); + va_end(ap); - if (!contactPoint->active) - continue; - - if (contactPoint->externalId == externalId) - { - contactIdlocal = contactPoint->contactId; - break; - } - } - - if (contactIdlocal >= 0) - { - ZeroMemory(&contact, sizeof(RDPINPUT_CONTACT_DATA)); - - if ((contactPoint->lastX != x) && (contactPoint->lastY != y)) - { - if ((error = context->TouchUpdate(context, externalId, x, y, &tempvalue))) - { - WLog_ERR(TAG, "context->TouchUpdate failed with error %" PRIu32 "!", error); - return error; - } - } + return error; +} - contact.x = x; - contact.y = y; - contact.contactId = (UINT32)contactIdlocal; - contact.contactFlags |= CONTACT_FLAG_UP; +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rdpei_pen_update(RdpeiClientContext* context, INT32 externalId, UINT32 fieldFlags, + INT32 x, INT32 y, ...) +{ + UINT error; + va_list ap; - if ((error = context->AddContact(context, &contact))) - { - WLog_ERR(TAG, "context->AddContact failed with error %" PRIu32 "!", error); - return error; - } + va_start(ap, y); + error = rdpei_pen_process(context, externalId, + CONTACT_FLAG_UPDATE | CONTACT_FLAG_INRANGE | CONTACT_FLAG_INCONTACT, + fieldFlags, x, y, ap); + va_end(ap); + return error; +} - contactPoint->externalId = 0; - contactPoint->active = FALSE; - contactPoint->flags = 0; - contactPoint->contactId = 0; - contactPoint->state = RDPINPUT_CONTACT_STATE_OUT_OF_RANGE; - } +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rdpei_pen_end(RdpeiClientContext* context, INT32 externalId, UINT32 fieldFlags, INT32 x, + INT32 y, ...) +{ + UINT error; + va_list ap; - *contactId = contactIdlocal; - return CHANNEL_RC_OK; + va_start(ap, y); + error = rdpei_pen_process(context, externalId, + CONTACT_FLAG_UPDATE | CONTACT_FLAG_INRANGE | CONTACT_FLAG_INCONTACT, + fieldFlags, x, y, ap); + if (error == CHANNEL_RC_OK) + error = rdpei_pen_process(context, externalId, CONTACT_FLAG_UP, fieldFlags, x, y, ap); + va_end(ap); + return error; } #ifdef BUILTIN_CHANNELS @@ -871,7 +1330,6 @@ if (!rdpei) { - size_t size; rdpei = (RDPEI_PLUGIN*)calloc(1, sizeof(RDPEI_PLUGIN)); if (!rdpei) @@ -884,24 +1342,15 @@ rdpei->iface.Connected = NULL; rdpei->iface.Disconnected = NULL; rdpei->iface.Terminated = rdpei_plugin_terminated; - rdpei->version = 1; + rdpei->version = RDPINPUT_PROTOCOL_V300; rdpei->currentFrameTime = 0; rdpei->previousFrameTime = 0; - rdpei->frame.contacts = (RDPINPUT_CONTACT_DATA*)rdpei->contacts; - rdpei->maxTouchContacts = 10; - size = rdpei->maxTouchContacts * sizeof(RDPINPUT_CONTACT_POINT); - rdpei->contactPoints = (RDPINPUT_CONTACT_POINT*)calloc(1, size); + rdpei->maxTouchContacts = MAX_CONTACTS; + rdpei->maxPenContacts = MAX_PEN_CONTACTS; rdpei->rdpcontext = ((freerdp*)((rdpSettings*)pEntryPoints->GetRdpSettings(pEntryPoints))->instance) ->context; - if (!rdpei->contactPoints) - { - WLog_ERR(TAG, "calloc failed!"); - error = CHANNEL_RC_NO_MEMORY; - goto error_out; - } - context = (RdpeiClientContext*)calloc(1, sizeof(RdpeiClientContext)); if (!context) @@ -913,10 +1362,15 @@ context->handle = (void*)rdpei; context->GetVersion = rdpei_get_version; + context->GetFeatures = rdpei_get_features; context->AddContact = rdpei_add_contact; context->TouchBegin = rdpei_touch_begin; context->TouchUpdate = rdpei_touch_update; context->TouchEnd = rdpei_touch_end; + context->AddPen = rdpei_add_pen; + context->PenBegin = rdpei_pen_begin; + context->PenUpdate = rdpei_pen_update; + context->PenEnd = rdpei_pen_end; rdpei->iface.pInterface = (void*)context; if ((error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpei", (IWTSPlugin*)rdpei))) diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpei/client/rdpei_main.h freerdp2-2.3.0+dfsg1/channels/rdpei/client/rdpei_main.h --- freerdp2-2.2.0+dfsg1/channels/rdpei/client/rdpei_main.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpei/client/rdpei_main.h 2021-02-25 08:51:41.000000000 +0000 @@ -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 diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpei/rdpei_common.c freerdp2-2.3.0+dfsg1/channels/rdpei/rdpei_common.c --- freerdp2-2.2.0+dfsg1/channels/rdpei/rdpei_common.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpei/rdpei_common.c 2021-02-25 08:51:41.000000000 +0000 @@ -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 @@ 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 @@ 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 @@ 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 @@ { BYTE byte; + if (!Stream_EnsureRemainingCapacity(s, 4)) + return FALSE; + if (value <= 0x3FUL) { Stream_Write_UINT8(s, value); @@ -300,6 +309,9 @@ BYTE byte; BOOL negative = FALSE; + if (!Stream_EnsureRemainingCapacity(s, 4)) + return FALSE; + if (value < 0) { negative = TRUE; @@ -478,6 +490,9 @@ { BYTE byte; + if (!Stream_EnsureRemainingCapacity(s, 8)) + return FALSE; + if (value <= 0x1FULL) { byte = value & 0x1F; @@ -501,7 +516,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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]); @@ -605,5 +620,24 @@ { free(frame->contacts); 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; } diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpei/rdpei_common.h freerdp2-2.3.0+dfsg1/channels/rdpei/rdpei_common.h --- freerdp2-2.2.0+dfsg1/channels/rdpei/rdpei_common.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpei/rdpei_common.h 2021-02-25 08:51:41.000000000 +0000 @@ -33,13 +33,14 @@ 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 @@ 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 */ diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpei/server/rdpei_main.c freerdp2-2.3.0+dfsg1/channels/rdpei/server/rdpei_main.c --- freerdp2-2.2.0+dfsg1/channels/rdpei/server/rdpei_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpei/server/rdpei_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -55,6 +55,7 @@ UINT16 currentMsgType; RDPINPUT_TOUCH_EVENT touchEvent; + RDPINPUT_PEN_EVENT penEvent; enum RdpEiState automataState; }; @@ -69,26 +70,22 @@ 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_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 @@ { 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_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 @@ } 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 @@ 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_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 @@ 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_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 @@ 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 @@ 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 @@ 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 @@ 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)) diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpgfx/client/rdpgfx_main.c freerdp2-2.3.0+dfsg1/channels/rdpgfx/client/rdpgfx_main.c --- freerdp2-2.2.0+dfsg1/channels/rdpgfx/client/rdpgfx_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpgfx/client/rdpgfx_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -1878,6 +1878,11 @@ { 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 @@ &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; } diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpgfx/client/rdpgfx_main.h freerdp2-2.3.0+dfsg1/channels/rdpgfx/client/rdpgfx_main.h --- freerdp2-2.2.0+dfsg1/channels/rdpgfx/client/rdpgfx_main.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpgfx/client/rdpgfx_main.h 2021-02-25 08:51:41.000000000 +0000 @@ -85,6 +85,7 @@ wLog* log; RDPGFX_CAPSET ConnectionCaps; BOOL SendQoeAck; + BOOL initialized; }; typedef struct _RDPGFX_PLUGIN RDPGFX_PLUGIN; diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpgfx/rdpgfx_common.c freerdp2-2.3.0+dfsg1/channels/rdpgfx/rdpgfx_common.c --- freerdp2-2.2.0+dfsg1/channels/rdpgfx/rdpgfx_common.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpgfx/rdpgfx_common.c 2021-02-25 08:51:41.000000000 +0000 @@ -129,6 +129,8 @@ */ 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) */ diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpgfx/server/rdpgfx_main.c freerdp2-2.3.0+dfsg1/channels/rdpgfx/server/rdpgfx_main.c --- freerdp2-2.2.0+dfsg1/channels/rdpgfx/server/rdpgfx_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpgfx/server/rdpgfx_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -72,13 +72,17 @@ * @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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ } 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 @@ 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 @@ 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 @@ 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); diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpsnd/client/mac/rdpsnd_mac.m freerdp2-2.3.0+dfsg1/channels/rdpsnd/client/mac/rdpsnd_mac.m --- freerdp2-2.2.0+dfsg1/channels/rdpsnd/client/mac/rdpsnd_mac.m 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpsnd/client/mac/rdpsnd_mac.m 2021-02-25 08:51:41.000000000 +0000 @@ -167,22 +167,14 @@ 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 @@ [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 @@ 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; diff -Nru freerdp2-2.2.0+dfsg1/channels/rdpsnd/client/rdpsnd_main.c freerdp2-2.3.0+dfsg1/channels/rdpsnd/client/rdpsnd_main.c --- freerdp2-2.2.0+dfsg1/channels/rdpsnd/client/rdpsnd_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/rdpsnd/client/rdpsnd_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -125,6 +125,7 @@ HANDLE thread; wMessageQueue* queue; + BOOL initialized; }; static const char* rdpsnd_is_dyn_str(BOOL dynamic) @@ -494,6 +495,38 @@ 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 @@ 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 @@ { 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 @@ 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; } /** diff -Nru freerdp2-2.2.0+dfsg1/channels/smartcard/client/CMakeLists.txt freerdp2-2.3.0+dfsg1/channels/smartcard/client/CMakeLists.txt --- freerdp2-2.2.0+dfsg1/channels/smartcard/client/CMakeLists.txt 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/smartcard/client/CMakeLists.txt 2021-02-25 08:51:41.000000000 +0000 @@ -22,6 +22,7 @@ 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") diff -Nru freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_main.c freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_main.c --- freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -209,6 +209,7 @@ * 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 @@ 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 @@ free(pKeys); } + ListDictionary_Unlock(smartcard->rgSCardContextList); } static UINT smartcard_free_(SMARTCARD_DEVICE* smartcard) diff -Nru freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_main.h freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_main.h --- freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_main.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_main.h 2021-02-25 08:51:41.000000000 +0000 @@ -32,76 +32,12 @@ #include #include -#define TAG CHANNELS_TAG("smartcard.client") - -#define RDP_SCARD_CTL_CODE(code) \ - CTL_CODE(FILE_DEVICE_FILE_SYSTEM, (code), METHOD_BUFFERED, FILE_ANY_ACCESS) +#include "smartcard_operations.h" -#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 */ +#define TAG CHANNELS_TAG("smartcard.client") 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; diff -Nru freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_operations.c freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_operations.c --- freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_operations.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_operations.c 2021-02-25 08:51:41.000000000 +0000 @@ -37,8 +37,22 @@ #include #include +#include "smartcard_operations.h" #include "smartcard_main.h" +static LONG smartcard_call_to_operation_handle(SMARTCARD_DEVICE* smartcard, + SMARTCARD_OPERATION* operation) +{ + if (!smartcard || !operation) + return SCARD_E_INVALID_HANDLE; + operation->hContext = + smartcard_scard_context_native_from_redir(smartcard, &(operation->call.handles.hContext)); + operation->hCard = + smartcard_scard_handle_native_from_redir(smartcard, &(operation->call.handles.hCard)); + + return SCARD_S_SUCCESS; +} + static LONG log_status_error(const char* tag, const char* what, LONG status) { if (status != SCARD_S_SUCCESS) @@ -218,14 +232,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - EstablishContext_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(EstablishContext_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; - status = smartcard_unpack_establish_context_call(smartcard, irp->input, call); + irp = operation->irp; + status = smartcard_unpack_establish_context_call(smartcard, irp->input, + &operation->call.establishContext); if (status != SCARD_S_SUCCESS) { return log_status_error(TAG, "smartcard_unpack_establish_context_call", status); @@ -239,9 +253,9 @@ { LONG status; SCARDCONTEXT hContext = { 0 }; - EstablishContext_Return ret; + EstablishContext_Return ret = { 0 }; IRP* irp = operation->irp; - EstablishContext_Call* call = operation->call; + EstablishContext_Call* call = &operation->call.establishContext; status = ret.ReturnCode = SCardEstablishContext(call->dwScope, NULL, NULL, &hContext); if (ret.ReturnCode == SCARD_S_SUCCESS) @@ -283,25 +297,24 @@ SMARTCARD_OPERATION* operation) { LONG status; - Context_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(Context_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; - status = smartcard_unpack_context_call(smartcard, irp->input, call, "ReleaseContext"); + irp = operation->irp; + status = smartcard_unpack_context_call(smartcard, irp->input, &operation->call.context, + "ReleaseContext"); if (status != SCARD_S_SUCCESS) log_status_error(TAG, "smartcard_unpack_context_call", status); - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } static LONG smartcard_ReleaseContext_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; + Long_Return ret = { 0 }; ret.ReturnCode = SCardReleaseContext(operation->hContext); if (ret.ReturnCode == SCARD_S_SUCCESS) @@ -324,23 +337,22 @@ SMARTCARD_OPERATION* operation) { LONG status; - Context_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(Context_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; - status = smartcard_unpack_context_call(smartcard, irp->input, call, "IsValidContext"); + irp = operation->irp; + status = smartcard_unpack_context_call(smartcard, irp->input, &operation->call.context, + "IsValidContext"); - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } static LONG smartcard_IsValidContext_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; + Long_Return ret = { 0 }; ret.ReturnCode = SCardIsValidContext(operation->hContext); smartcard_trace_long_return(smartcard, &ret, "IsValidContext"); @@ -351,16 +363,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - ListReaderGroups_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ListReaderGroups_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_list_reader_groups_call(smartcard, irp->input, + &operation->call.listReaderGroups, FALSE); - status = smartcard_unpack_list_reader_groups_call(smartcard, irp->input, call, FALSE); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -368,19 +378,15 @@ SMARTCARD_OPERATION* operation) { LONG status; - ListReaderGroups_Return ret; + ListReaderGroups_Return ret = { 0 }; LPSTR mszGroups = NULL; DWORD cchGroups = 0; IRP* irp = operation->irp; cchGroups = SCARD_AUTOALLOCATE; - status = ret.ReturnCode = - SCardListReaderGroupsA(operation->hContext, (LPSTR)&mszGroups, &cchGroups); + ret.ReturnCode = SCardListReaderGroupsA(operation->hContext, (LPSTR)&mszGroups, &cchGroups); ret.msz = (BYTE*)mszGroups; ret.cBytes = cchGroups; - if (status != SCARD_S_SUCCESS) - return status; - status = smartcard_pack_list_reader_groups_return(smartcard, irp->output, &ret, FALSE); if (status != SCARD_S_SUCCESS) @@ -396,16 +402,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - ListReaderGroups_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ListReaderGroups_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_list_reader_groups_call(smartcard, irp->input, + &operation->call.listReaderGroups, TRUE); - status = smartcard_unpack_list_reader_groups_call(smartcard, irp->input, call, TRUE); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -413,15 +417,20 @@ SMARTCARD_OPERATION* operation) { LONG status; - ListReaderGroups_Return ret; + ListReaderGroups_Return ret = { 0 }; LPWSTR mszGroups = NULL; DWORD cchGroups = 0; - IRP* irp = operation->irp; + IRP* irp; + + if (!operation || !operation->irp) + return STATUS_NO_MEMORY; + + irp = operation->irp; cchGroups = SCARD_AUTOALLOCATE; status = ret.ReturnCode = SCardListReaderGroupsW(operation->hContext, (LPWSTR)&mszGroups, &cchGroups); ret.msz = (BYTE*)mszGroups; - ret.cBytes = cchGroups; + ret.cBytes = cchGroups * sizeof(WCHAR); if (status != SCARD_S_SUCCESS) return status; @@ -525,27 +534,25 @@ SMARTCARD_OPERATION* operation) { LONG status; - ListReaders_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ListReaders_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_list_readers_call(smartcard, irp->input, &operation->call.listReaders, + FALSE); - status = smartcard_unpack_list_readers_call(smartcard, irp->input, call, FALSE); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } static LONG smartcard_ListReadersA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - ListReaders_Return ret; + ListReaders_Return ret = { 0 }; LPSTR mszReaders = NULL; DWORD cchReaders = 0; IRP* irp = operation->irp; - ListReaders_Call* call = operation->call; + ListReaders_Call* call = &operation->call.listReaders; cchReaders = SCARD_AUTOALLOCATE; status = ret.ReturnCode = SCardListReadersA(operation->hContext, (LPCSTR)call->mszGroups, (LPSTR)&mszReaders, &cchReaders); @@ -584,16 +591,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - ListReaders_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ListReaders_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_list_readers_call(smartcard, irp->input, &operation->call.listReaders, + TRUE); - status = smartcard_unpack_list_readers_call(smartcard, irp->input, call, TRUE); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -601,16 +606,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - ContextAndTwoStringA_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ContextAndTwoStringA_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_context_and_two_strings_a_call(smartcard, irp->input, + &operation->call.contextAndTwoStringA); - status = smartcard_unpack_context_and_two_strings_a_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -618,16 +621,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - ContextAndTwoStringW_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ContextAndTwoStringW_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_context_and_two_strings_w_call(smartcard, irp->input, + &operation->call.contextAndTwoStringW); - status = smartcard_unpack_context_and_two_strings_w_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -635,16 +636,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - ContextAndStringA_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ContextAndStringA_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_context_and_string_a_call(smartcard, irp->input, + &operation->call.contextAndStringA); - status = smartcard_unpack_context_and_string_a_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -652,16 +651,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - ContextAndStringW_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ContextAndStringW_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_context_and_string_w_call(smartcard, irp->input, + &operation->call.contextAndStringW); - status = smartcard_unpack_context_and_string_w_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -669,16 +666,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - LocateCardsA_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(LocateCardsA_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = + smartcard_unpack_locate_cards_a_call(smartcard, irp->input, &operation->call.locateCardsA); - status = smartcard_unpack_locate_cards_a_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -686,26 +681,24 @@ SMARTCARD_OPERATION* operation) { LONG status; - LocateCardsW_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(LocateCardsW_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = + smartcard_unpack_locate_cards_w_call(smartcard, irp->input, &operation->call.locateCardsW); - status = smartcard_unpack_locate_cards_w_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } static LONG smartcard_ListReadersW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - ListReaders_Return ret; + ListReaders_Return ret = { 0 }; DWORD cchReaders = 0; IRP* irp = operation->irp; - ListReaders_Call* call = operation->call; + ListReaders_Call* call = &operation->call.listReaders; union { const BYTE* bp; const char* sz; @@ -749,8 +742,8 @@ static LONG smartcard_IntroduceReaderGroupA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - ContextAndStringA_Call* call = operation->call; + Long_Return ret = { 0 }; + ContextAndStringA_Call* call = &operation->call.contextAndStringA; ret.ReturnCode = SCardIntroduceReaderGroupA(operation->hContext, call->sz); log_status_error(TAG, "SCardIntroduceReaderGroupA", ret.ReturnCode); if (call->sz) @@ -766,8 +759,8 @@ static LONG smartcard_IntroduceReaderGroupW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - ContextAndStringW_Call* call = operation->call; + Long_Return ret = { 0 }; + ContextAndStringW_Call* call = &operation->call.contextAndStringW; ret.ReturnCode = SCardIntroduceReaderGroupW(operation->hContext, call->sz); log_status_error(TAG, "SCardIntroduceReaderGroupW", ret.ReturnCode); if (call->sz) @@ -783,8 +776,8 @@ static LONG smartcard_IntroduceReaderA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - ContextAndTwoStringA_Call* call = operation->call; + Long_Return ret = { 0 }; + ContextAndTwoStringA_Call* call = &operation->call.contextAndTwoStringA; ret.ReturnCode = SCardIntroduceReaderA(operation->hContext, call->sz1, call->sz2); log_status_error(TAG, "SCardIntroduceReaderA", ret.ReturnCode); free(call->sz1); @@ -799,8 +792,8 @@ static LONG smartcard_IntroduceReaderW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - ContextAndTwoStringW_Call* call = operation->call; + Long_Return ret = { 0 }; + ContextAndTwoStringW_Call* call = &operation->call.contextAndTwoStringW; ret.ReturnCode = SCardIntroduceReaderW(operation->hContext, call->sz1, call->sz2); log_status_error(TAG, "SCardIntroduceReaderW", ret.ReturnCode); free(call->sz1); @@ -815,8 +808,8 @@ static LONG smartcard_ForgetReaderA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - ContextAndStringA_Call* call = operation->call; + Long_Return ret = { 0 }; + ContextAndStringA_Call* call = &operation->call.contextAndStringA; ret.ReturnCode = SCardForgetReaderA(operation->hContext, call->sz); log_status_error(TAG, "SCardForgetReaderA", ret.ReturnCode); if (call->sz) @@ -832,8 +825,8 @@ static LONG smartcard_ForgetReaderW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - ContextAndStringW_Call* call = operation->call; + Long_Return ret = { 0 }; + ContextAndStringW_Call* call = &operation->call.contextAndStringW; ret.ReturnCode = SCardForgetReaderW(operation->hContext, call->sz); log_status_error(TAG, "SCardForgetReaderW", ret.ReturnCode); if (call->sz) @@ -849,8 +842,8 @@ static LONG smartcard_AddReaderToGroupA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - ContextAndTwoStringA_Call* call = operation->call; + Long_Return ret = { 0 }; + ContextAndTwoStringA_Call* call = &operation->call.contextAndTwoStringA; ret.ReturnCode = SCardAddReaderToGroupA(operation->hContext, call->sz1, call->sz2); log_status_error(TAG, "SCardAddReaderToGroupA", ret.ReturnCode); free(call->sz1); @@ -865,8 +858,8 @@ static LONG smartcard_AddReaderToGroupW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - ContextAndTwoStringW_Call* call = operation->call; + Long_Return ret = { 0 }; + ContextAndTwoStringW_Call* call = &operation->call.contextAndTwoStringW; ret.ReturnCode = SCardAddReaderToGroupW(operation->hContext, call->sz1, call->sz2); log_status_error(TAG, "SCardAddReaderToGroupW", ret.ReturnCode); free(call->sz1); @@ -881,8 +874,8 @@ static LONG smartcard_RemoveReaderFromGroupA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - ContextAndTwoStringA_Call* call = operation->call; + Long_Return ret = { 0 }; + ContextAndTwoStringA_Call* call = &operation->call.contextAndTwoStringA; ret.ReturnCode = SCardRemoveReaderFromGroupA(operation->hContext, call->sz1, call->sz2); log_status_error(TAG, "SCardRemoveReaderFromGroupA", ret.ReturnCode); free(call->sz1); @@ -897,8 +890,8 @@ static LONG smartcard_RemoveReaderFromGroupW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - ContextAndTwoStringW_Call* call = operation->call; + Long_Return ret = { 0 }; + ContextAndTwoStringW_Call* call = &operation->call.contextAndTwoStringW; ret.ReturnCode = SCardRemoveReaderFromGroupW(operation->hContext, call->sz1, call->sz2); log_status_error(TAG, "SCardRemoveReaderFromGroupW", ret.ReturnCode); free(call->sz1); @@ -914,8 +907,8 @@ { UINT32 x; LONG status; - LocateCards_Return ret; - LocateCardsA_Call* call = operation->call; + LocateCards_Return ret = { 0 }; + LocateCardsA_Call* call = &operation->call.locateCardsA; IRP* irp = operation->irp; ret.ReturnCode = SCardLocateCardsA(operation->hContext, call->mszCards, call->rgReaderStates, @@ -963,8 +956,8 @@ { UINT32 x; LONG status; - LocateCards_Return ret; - LocateCardsW_Call* call = operation->call; + LocateCards_Return ret = { 0 }; + LocateCardsW_Call* call = &operation->call.locateCardsW; IRP* irp = operation->irp; ret.ReturnCode = SCardLocateCardsW(operation->hContext, call->mszCards, call->rgReaderStates, @@ -1012,7 +1005,7 @@ { LONG status; ReadCache_Return ret = { 0 }; - ReadCacheA_Call* call = operation->call; + ReadCacheA_Call* call = &operation->call.readCacheA; IRP* irp = operation->irp; BOOL autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE); @@ -1058,7 +1051,7 @@ { LONG status; ReadCache_Return ret = { 0 }; - ReadCacheW_Call* call = operation->call; + ReadCacheW_Call* call = &operation->call.readCacheW; IRP* irp = operation->irp; BOOL autoalloc = (call->Common.cbDataLen == SCARD_AUTOALLOCATE); if (!call->Common.fPbDataIsNULL) @@ -1101,8 +1094,8 @@ static LONG smartcard_WriteCacheA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - WriteCacheA_Call* call = operation->call; + Long_Return ret = { 0 }; + WriteCacheA_Call* call = &operation->call.writeCacheA; ret.ReturnCode = SCardWriteCacheA(operation->hContext, call->Common.CardIdentifier, call->Common.FreshnessCounter, call->szLookupName, @@ -1118,8 +1111,8 @@ static LONG smartcard_WriteCacheW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - WriteCacheW_Call* call = operation->call; + Long_Return ret = { 0 }; + WriteCacheW_Call* call = &operation->call.writeCacheW; ret.ReturnCode = SCardWriteCacheW(operation->hContext, call->Common.CardIdentifier, call->Common.FreshnessCounter, call->szLookupName, @@ -1137,10 +1130,10 @@ SMARTCARD_OPERATION* operation) { LONG status; - GetTransmitCount_Return ret; + GetTransmitCount_Return ret = { 0 }; IRP* irp = operation->irp; - ret.ReturnCode = SCardGetTransmitCount(operation->hContext, &ret.cTransmitCount); + ret.ReturnCode = SCardGetTransmitCount(operation->hCard, &ret.cTransmitCount); log_status_error(TAG, "SCardGetTransmitCount", ret.ReturnCode); status = smartcard_pack_get_transmit_count_return(smartcard, irp->output, &ret); if (status != SCARD_S_SUCCESS) @@ -1165,7 +1158,7 @@ { LONG status; GetReaderIcon_Return ret = { 0 }; - GetReaderIcon_Call* call = operation->call; + GetReaderIcon_Call* call = &operation->call.getReaderIcon; IRP* irp = operation->irp; ret.cbDataLen = SCARD_AUTOALLOCATE; @@ -1185,8 +1178,8 @@ SMARTCARD_OPERATION* operation) { LONG status; - GetDeviceTypeId_Return ret; - GetDeviceTypeId_Call* call = operation->call; + GetDeviceTypeId_Return ret = { 0 }; + GetDeviceTypeId_Call* call = &operation->call.getDeviceTypeId; IRP* irp = operation->irp; ret.ReturnCode = @@ -1205,16 +1198,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - GetStatusChangeA_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(GetStatusChangeA_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_get_status_change_a_call(smartcard, irp->input, + &operation->call.getStatusChangeA); - status = smartcard_unpack_get_status_change_a_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -1222,10 +1213,10 @@ SMARTCARD_OPERATION* operation) { UINT32 index; - GetStatusChange_Return ret; + GetStatusChange_Return ret = { 0 }; LPSCARD_READERSTATEA rgReaderState = NULL; IRP* irp = operation->irp; - GetStatusChangeA_Call* call = operation->call; + GetStatusChangeA_Call* call = &operation->call.getStatusChangeA; ret.ReturnCode = SCardGetStatusChangeA(operation->hContext, call->dwTimeOut, call->rgReaderStates, call->cReaders); log_status_error(TAG, "SCardGetStatusChangeA", ret.ReturnCode); @@ -1270,27 +1261,26 @@ SMARTCARD_OPERATION* operation) { LONG status; - GetStatusChangeW_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(GetStatusChangeW_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_get_status_change_w_call(smartcard, irp->input, + &operation->call.getStatusChangeW); - status = smartcard_unpack_get_status_change_w_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } static LONG smartcard_GetStatusChangeW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { + LONG status; UINT32 index; - GetStatusChange_Return ret; + GetStatusChange_Return ret = { 0 }; LPSCARD_READERSTATEW rgReaderState = NULL; IRP* irp = operation->irp; - GetStatusChangeW_Call* call = operation->call; + GetStatusChangeW_Call* call = &operation->call.getStatusChangeW; ret.ReturnCode = SCardGetStatusChangeW(operation->hContext, call->dwTimeOut, call->rgReaderStates, call->cReaders); log_status_error(TAG, "SCardGetStatusChangeW", ret.ReturnCode); @@ -1314,7 +1304,7 @@ sizeof(ret.rgReaderStates[index].rgbAtr)); } - smartcard_pack_get_status_change_return(smartcard, irp->output, &ret, TRUE); + status = smartcard_pack_get_status_change_return(smartcard, irp->output, &ret, TRUE); if (call->rgReaderStates) { @@ -1328,28 +1318,28 @@ } free(ret.rgReaderStates); + if (status != SCARD_S_SUCCESS) + return status; return ret.ReturnCode; } static LONG smartcard_Cancel_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - Context_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(Context_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = + smartcard_unpack_context_call(smartcard, irp->input, &operation->call.context, "Cancel"); - status = smartcard_unpack_context_call(smartcard, irp->input, call, "Cancel"); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } static LONG smartcard_Cancel_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; + Long_Return ret = { 0 }; ret.ReturnCode = SCardCancel(operation->hContext); log_status_error(TAG, "SCardCancel", ret.ReturnCode); @@ -1360,17 +1350,13 @@ static LONG smartcard_ConnectA_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - ConnectA_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ConnectA_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_connect_a_call(smartcard, irp->input, &operation->call.connectA); - status = smartcard_unpack_connect_a_call(smartcard, irp->input, call); - - operation->hContext = - smartcard_scard_context_native_from_redir(smartcard, &(call->Common.hContext)); return status; } @@ -1380,7 +1366,7 @@ SCARDHANDLE hCard = 0; Connect_Return ret = { 0 }; IRP* irp = operation->irp; - ConnectA_Call* call = operation->call; + ConnectA_Call* call = &operation->call.connectA; if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) && (call->Common.dwShareMode != SCARD_SHARE_DIRECT)) @@ -1388,7 +1374,7 @@ call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx; } - status = ret.ReturnCode = + ret.ReturnCode = SCardConnectA(operation->hContext, (char*)call->szReader, call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol); smartcard_scard_context_native_to_redir(smartcard, &(ret.hContext), operation->hContext); @@ -1407,17 +1393,13 @@ static LONG smartcard_ConnectW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - ConnectW_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ConnectW_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_connect_w_call(smartcard, irp->input, &operation->call.connectW); - status = smartcard_unpack_connect_w_call(smartcard, irp->input, call); - - operation->hContext = - smartcard_scard_context_native_from_redir(smartcard, &(call->Common.hContext)); return status; } @@ -1427,7 +1409,7 @@ SCARDHANDLE hCard = 0; Connect_Return ret = { 0 }; IRP* irp = operation->irp; - ConnectW_Call* call = operation->call; + ConnectW_Call* call = &operation->call.connectW; if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) && (call->Common.dwShareMode != SCARD_SHARE_DIRECT)) @@ -1435,7 +1417,7 @@ call->Common.dwPreferredProtocols = SCARD_PROTOCOL_Tx; } - status = ret.ReturnCode = + ret.ReturnCode = SCardConnectW(operation->hContext, (WCHAR*)call->szReader, call->Common.dwShareMode, call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol); smartcard_scard_context_native_to_redir(smartcard, &(ret.hContext), operation->hContext); @@ -1454,26 +1436,22 @@ static LONG smartcard_Reconnect_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - Reconnect_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(Reconnect_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_reconnect_call(smartcard, irp->input, &operation->call.reconnect); - status = smartcard_unpack_reconnect_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); - operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard)); return status; } static LONG smartcard_Reconnect_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - Reconnect_Return ret; + Reconnect_Return ret = { 0 }; IRP* irp = operation->irp; - Reconnect_Call* call = operation->call; + Reconnect_Call* call = &operation->call.reconnect; ret.ReturnCode = SCardReconnect(operation->hCard, call->dwShareMode, call->dwPreferredProtocols, call->dwInitialization, &ret.dwActiveProtocol); log_status_error(TAG, "SCardReconnect", ret.ReturnCode); @@ -1487,24 +1465,21 @@ static LONG smartcard_Disconnect_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - HCardAndDisposition_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(HCardAndDisposition_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_hcard_and_disposition_call( + smartcard, irp->input, &operation->call.hCardAndDisposition, "Disconnect"); - status = smartcard_unpack_hcard_and_disposition_call(smartcard, irp->input, call, "Disconnect"); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); - operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard)); return status; } static LONG smartcard_Disconnect_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - HCardAndDisposition_Call* call = operation->call; + Long_Return ret = { 0 }; + HCardAndDisposition_Call* call = &operation->call.hCardAndDisposition; ret.ReturnCode = SCardDisconnect(operation->hCard, call->dwDisposition); log_status_error(TAG, "SCardDisconnect", ret.ReturnCode); @@ -1517,25 +1492,21 @@ SMARTCARD_OPERATION* operation) { LONG status; - HCardAndDisposition_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(HCardAndDisposition_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_hcard_and_disposition_call( + smartcard, irp->input, &operation->call.hCardAndDisposition, "BeginTransaction"); - status = smartcard_unpack_hcard_and_disposition_call(smartcard, irp->input, call, - "BeginTransaction"); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); - operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard)); return status; } static LONG smartcard_BeginTransaction_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; + Long_Return ret = { 0 }; ret.ReturnCode = SCardBeginTransaction(operation->hCard); log_status_error(TAG, "SCardBeginTransaction", ret.ReturnCode); @@ -1547,26 +1518,22 @@ SMARTCARD_OPERATION* operation) { LONG status; - HCardAndDisposition_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(HCardAndDisposition_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_hcard_and_disposition_call( + smartcard, irp->input, &operation->call.hCardAndDisposition, "EndTransaction"); - status = - smartcard_unpack_hcard_and_disposition_call(smartcard, irp->input, call, "EndTransaction"); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); - operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard)); return status; } static LONG smartcard_EndTransaction_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - HCardAndDisposition_Call* call = operation->call; + Long_Return ret = { 0 }; + HCardAndDisposition_Call* call = &operation->call.hCardAndDisposition; ret.ReturnCode = SCardEndTransaction(operation->hCard, call->dwDisposition); log_status_error(TAG, "SCardEndTransaction", ret.ReturnCode); @@ -1577,24 +1544,20 @@ static LONG smartcard_State_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - State_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(State_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_state_call(smartcard, irp->input, &operation->call.state); - status = smartcard_unpack_state_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); - operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard)); return status; } static LONG smartcard_State_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - State_Return ret; + State_Return ret = { 0 }; IRP* irp = operation->irp; ret.cbAtrLen = SCARD_ATR_LENGTH; ret.ReturnCode = SCardState(operation->hCard, &ret.dwState, &ret.dwProtocol, (BYTE*)&ret.rgAtr, @@ -1611,17 +1574,13 @@ static LONG smartcard_StatusA_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - Status_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(Status_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_status_call(smartcard, irp->input, &operation->call.status, FALSE); - status = smartcard_unpack_status_call(smartcard, irp->input, call, FALSE); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); - operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard)); return status; } @@ -1633,7 +1592,7 @@ DWORD cbAtrLen = 0; LPSTR mszReaderNames = NULL; IRP* irp = operation->irp; - Status_Call* call = operation->call; + Status_Call* call = &operation->call.status; call->cbAtrLen = 32; cbAtrLen = call->cbAtrLen; @@ -1673,17 +1632,13 @@ static LONG smartcard_StatusW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - Status_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(Status_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_status_call(smartcard, irp->input, &operation->call.status, TRUE); - status = smartcard_unpack_status_call(smartcard, irp->input, call, TRUE); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); - operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard)); return status; } @@ -1693,7 +1648,7 @@ Status_Return ret = { 0 }; LPWSTR mszReaderNames = NULL; IRP* irp = operation->irp; - Status_Call* call = operation->call; + Status_Call* call = &operation->call.status; DWORD cbAtrLen; /** @@ -1719,6 +1674,9 @@ ret.cbAtrLen = cbAtrLen; } + /* SCardStatusW returns number of characters, we need number of bytes */ + ret.cBytes *= sizeof(WCHAR); + status = smartcard_pack_status_return(smartcard, irp->output, &ret, TRUE); if (status != SCARD_S_SUCCESS) return status; @@ -1732,26 +1690,22 @@ static LONG smartcard_Transmit_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - Transmit_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(Transmit_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_transmit_call(smartcard, irp->input, &operation->call.transmit); - status = smartcard_unpack_transmit_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); - operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard)); return status; } static LONG smartcard_Transmit_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - Transmit_Return ret; + Transmit_Return ret = { 0 }; IRP* irp = operation->irp; - Transmit_Call* call = operation->call; + Transmit_Call* call = &operation->call.transmit; ret.cbRecvLength = 0; ret.pbRecvBuffer = NULL; @@ -1788,17 +1742,13 @@ static LONG smartcard_Control_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - Control_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(Control_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_control_call(smartcard, irp->input, &operation->call.control); - status = smartcard_unpack_control_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); - operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard)); return status; } @@ -1807,7 +1757,7 @@ LONG status; Control_Return ret = { 0 }; IRP* irp = operation->irp; - Control_Call* call = operation->call; + Control_Call* call = &operation->call.control; ret.cbOutBufferSize = call->cbOutBufferSize; ret.pvOutBuffer = (BYTE*)malloc(call->cbOutBufferSize); @@ -1830,68 +1780,60 @@ static LONG smartcard_GetAttrib_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - GetAttrib_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(GetAttrib_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_get_attrib_call(smartcard, irp->input, &operation->call.getAttrib); - status = smartcard_unpack_get_attrib_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); - operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard)); return status; } static LONG smartcard_SetAttrib_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - SetAttrib_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(SetAttrib_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_set_attrib_call(smartcard, irp->input, &operation->call.setAttrib); - status = smartcard_unpack_set_attrib_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); - operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard)); return status; } static LONG smartcard_GetAttrib_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { + BOOL autoAllocate = FALSE; LONG status; - DWORD cbAttrLen; - BOOL autoAllocate; - GetAttrib_Return ret; + DWORD cbAttrLen = 0; + LPBYTE pbAttr = NULL; + GetAttrib_Return ret = { 0 }; IRP* irp = operation->irp; - GetAttrib_Call* call = operation->call; - ret.pbAttr = NULL; - - if (call->fpbAttrIsNULL) - call->cbAttrLen = 0; + const GetAttrib_Call* call = &operation->call.getAttrib; - autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE) ? TRUE : FALSE; - - if (call->cbAttrLen && !autoAllocate) + if (!call->fpbAttrIsNULL) { - ret.pbAttr = (BYTE*)malloc(call->cbAttrLen); + autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE) ? TRUE : FALSE; + cbAttrLen = call->cbAttrLen; + if (cbAttrLen && !autoAllocate) + { + ret.pbAttr = (BYTE*)malloc(cbAttrLen); + + if (!ret.pbAttr) + return SCARD_E_NO_MEMORY; + } - if (!ret.pbAttr) - return SCARD_E_NO_MEMORY; + pbAttr = autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr; } - cbAttrLen = call->cbAttrLen; - ret.ReturnCode = - SCardGetAttrib(operation->hCard, call->dwAttrId, - autoAllocate ? (LPBYTE) & (ret.pbAttr) : ret.pbAttr, &cbAttrLen); + ret.ReturnCode = SCardGetAttrib(operation->hCard, call->dwAttrId, pbAttr, &cbAttrLen); log_status_error(TAG, "SCardGetAttrib", ret.ReturnCode); ret.cbAttrLen = cbAttrLen; - status = smartcard_pack_get_attrib_return(smartcard, irp->output, &ret, call->dwAttrId); + status = smartcard_pack_get_attrib_return(smartcard, irp->output, &ret, call->dwAttrId, + call->cbAttrLen); if (autoAllocate) SCardFreeMemory(operation->hContext, ret.pbAttr); @@ -1902,8 +1844,8 @@ static LONG smartcard_SetAttrib_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Return ret; - SetAttrib_Call* call = operation->call; + Long_Return ret = { 0 }; + SetAttrib_Call* call = &operation->call.setAttrib; ret.ReturnCode = SCardSetAttrib(operation->hCard, call->dwAttrId, call->pbAttr, call->cbAttrLen); @@ -1917,13 +1859,11 @@ static LONG smartcard_AccessStartedEvent_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { - Long_Call* call; IRP* irp; WINPR_UNUSED(smartcard); irp = operation->irp; - operation->call = call = calloc(1, sizeof(Long_Call)); - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; if (Stream_GetRemainingLength(irp->input) < 4) @@ -1933,7 +1873,8 @@ return SCARD_F_INTERNAL_ERROR; } - Stream_Read_INT32(irp->input, call->LongValue); /* Unused (4 bytes) */ + Stream_Read_INT32(irp->input, operation->call.lng.LongValue); /* Unused (4 bytes) */ + return SCARD_S_SUCCESS; } @@ -1956,16 +1897,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - LocateCardsByATRA_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(LocateCardsByATRA_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_locate_cards_by_atr_a_call(smartcard, irp->input, + &operation->call.locateCardsByATRA); - status = smartcard_unpack_locate_cards_by_atr_a_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -1973,50 +1912,41 @@ SMARTCARD_OPERATION* operation) { LONG status; - LocateCardsByATRW_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(LocateCardsByATRW_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_locate_cards_by_atr_w_call(smartcard, irp->input, + &operation->call.locateCardsByATRW); - status = smartcard_unpack_locate_cards_by_atr_w_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } static LONG smartcard_ReadCacheA_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - ReadCacheA_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ReadCacheA_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_read_cache_a_call(smartcard, irp->input, &operation->call.readCacheA); - status = smartcard_unpack_read_cache_a_call(smartcard, irp->input, call); - - operation->hContext = - smartcard_scard_context_native_from_redir(smartcard, &(call->Common.hContext)); return status; } static LONG smartcard_ReadCacheW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation) { LONG status; - ReadCacheW_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(ReadCacheW_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; - status = smartcard_unpack_read_cache_w_call(smartcard, irp->input, call); + status = smartcard_unpack_read_cache_w_call(smartcard, irp->input, &operation->call.readCacheW); - operation->hContext = - smartcard_scard_context_native_from_redir(smartcard, &(call->Common.hContext)); return status; } @@ -2024,17 +1954,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - WriteCacheA_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(WriteCacheA_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = + smartcard_unpack_write_cache_a_call(smartcard, irp->input, &operation->call.writeCacheA); - status = smartcard_unpack_write_cache_a_call(smartcard, irp->input, call); - - operation->hContext = - smartcard_scard_context_native_from_redir(smartcard, &(call->Common.hContext)); return status; } @@ -2042,17 +1969,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - WriteCacheW_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(WriteCacheW_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = + smartcard_unpack_write_cache_w_call(smartcard, irp->input, &operation->call.writeCacheW); - status = smartcard_unpack_write_cache_w_call(smartcard, irp->input, call); - - operation->hContext = - smartcard_scard_context_native_from_redir(smartcard, &(call->Common.hContext)); return status; } @@ -2060,16 +1984,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - GetTransmitCount_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(GetTransmitCount_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_get_transmit_count_call(smartcard, irp->input, + &operation->call.getTransmitCount); - status = smartcard_unpack_get_transmit_count_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -2087,16 +2009,15 @@ SMARTCARD_OPERATION* operation) { LONG status; - GetReaderIcon_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(GetReaderIcon_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; - status = smartcard_unpack_get_reader_icon_call(smartcard, irp->input, call); + status = smartcard_unpack_get_reader_icon_call(smartcard, irp->input, + &operation->call.getReaderIcon); - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -2104,16 +2025,14 @@ SMARTCARD_OPERATION* operation) { LONG status; - GetDeviceTypeId_Call* call; - IRP* irp = operation->irp; - operation->call = call = calloc(1, sizeof(GetDeviceTypeId_Call)); + IRP* irp; - if (!call) + if (!operation || !operation->irp) return STATUS_NO_MEMORY; + irp = operation->irp; + status = smartcard_unpack_get_device_type_id_call(smartcard, irp->input, + &operation->call.getDeviceTypeId); - status = smartcard_unpack_get_device_type_id_call(smartcard, irp->input, call); - - operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext)); return status; } @@ -2122,11 +2041,11 @@ { LONG status; DWORD i, j, k; - GetStatusChange_Return ret; + GetStatusChange_Return ret = { 0 }; LPSCARD_READERSTATEA state = NULL; LPSCARD_READERSTATEA states = NULL; IRP* irp = operation->irp; - LocateCardsByATRA_Call* call = operation->call; + LocateCardsByATRA_Call* call = &operation->call.locateCardsByATRA; states = (LPSCARD_READERSTATEA)calloc(call->cReaders, sizeof(SCARD_READERSTATEA)); if (!states) @@ -2145,11 +2064,6 @@ SCardGetStatusChangeA(operation->hContext, 0x000001F4, states, call->cReaders); log_status_error(TAG, "SCardGetStatusChangeA", status); - if (status && (status != SCARD_E_TIMEOUT) && (status != SCARD_E_CANCELLED)) - { - call->cReaders = 0; - } - for (i = 0; i < call->cAtrs; i++) { for (j = 0; j < call->cReaders; j++) @@ -2192,8 +2106,6 @@ free(states); status = smartcard_pack_get_status_change_return(smartcard, irp->output, &ret, FALSE); - if (status != SCARD_S_SUCCESS) - return status; if (call->rgReaderStates) { @@ -2213,6 +2125,8 @@ } free(ret.rgReaderStates); + if (status != SCARD_S_SUCCESS) + return status; return ret.ReturnCode; } @@ -2224,7 +2138,11 @@ UINT32 ioControlCode; UINT32 outputBufferLength; UINT32 inputBufferLength; - IRP* irp = operation->irp; + IRP* irp; + + if (!operation || !operation->irp) + return SCARD_E_NO_MEMORY; + irp = operation->irp; /* Device Control Request */ @@ -2265,8 +2183,6 @@ } /* Decode */ - operation->call = NULL; - switch (ioControlCode) { case SCARD_IOCTL_ESTABLISHCONTEXT: @@ -2466,6 +2382,8 @@ break; } + smartcard_call_to_operation_handle(smartcard, operation); + if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) && (ioControlCode != SCARD_IOCTL_RELEASETARTEDEVENT)) { @@ -2498,12 +2416,6 @@ Stream_GetPosition(irp->input), Stream_Length(irp->input), difference); } - if (status != SCARD_S_SUCCESS) - { - free(operation->call); - operation->call = NULL; - } - return status; } @@ -2735,9 +2647,6 @@ break; } - free(operation->call); - operation->call = NULL; - /** * [MS-RPCE] 2.2.6.3 Primitive Type Serialization * The type MUST be aligned on an 8-byte boundary. If the size of the diff -Nru freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_operations.h freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_operations.h --- freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_operations.h 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_operations.h 2021-02-25 08:51:41.000000000 +0000 @@ -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 + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger + * + * 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 + +#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 */ diff -Nru freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_pack.c freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_pack.c --- freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_pack.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_pack.c 2021-02-25 08:51:41.000000000 +0000 @@ -256,7 +256,8 @@ static LONG smartcard_ndr_write_state(wStream* s, const ReaderState_Return* data, UINT32 size, ndr_ptr_t type) { - union { + union + { const ReaderState_Return* reader; const BYTE* data; } cnv; @@ -268,7 +269,8 @@ static LONG smartcard_ndr_read_atrmask(wStream* s, LocateCards_ATRMask** data, size_t min, ndr_ptr_t type) { - union { + union + { LocateCards_ATRMask** ppc; BYTE** ppv; } u; @@ -278,7 +280,8 @@ static LONG smartcard_ndr_read_fixed_string_a(wStream* s, CHAR** data, size_t min, ndr_ptr_t type) { - union { + union + { CHAR** ppc; BYTE** ppv; } u; @@ -288,7 +291,8 @@ static LONG smartcard_ndr_read_fixed_string_w(wStream* s, WCHAR** data, size_t min, ndr_ptr_t type) { - union { + union + { WCHAR** ppc; BYTE** ppv; } u; @@ -298,7 +302,8 @@ static LONG smartcard_ndr_read_a(wStream* s, CHAR** data, ndr_ptr_t type) { - union { + union + { CHAR** ppc; BYTE** ppv; } u; @@ -308,7 +313,8 @@ static LONG smartcard_ndr_read_w(wStream* s, WCHAR** data, ndr_ptr_t type) { - union { + union + { WCHAR** ppc; BYTE** ppv; } u; @@ -318,7 +324,8 @@ static LONG smartcard_ndr_read_u(wStream* s, UUID** data) { - union { + union + { UUID** ppc; BYTE** ppv; } u; @@ -329,7 +336,8 @@ static char* smartcard_convert_string_list(const void* in, size_t bytes, BOOL unicode) { size_t index, length; - union { + union + { const void* pv; const char* sz; const WCHAR* wz; @@ -488,7 +496,7 @@ return; WLog_LVL(TAG, g_LogLevel, "%s_Call {", name); - smartcard_log_context(TAG, &call->hContext); + smartcard_log_context(TAG, &call->handles.hContext); WLog_LVL(TAG, g_LogLevel, "}"); } @@ -502,7 +510,7 @@ return; WLog_LVL(TAG, g_LogLevel, "ListReaderGroups%S_Call {", unicode ? "W" : "A"); - smartcard_log_context(TAG, &call->hContext); + smartcard_log_context(TAG, &call->handles.hContext); WLog_LVL(TAG, g_LogLevel, "fmszGroupsIsNULL: %" PRId32 " cchGroups: 0x%08" PRIx32, call->fmszGroupsIsNULL, call->cchGroups); @@ -522,7 +530,7 @@ return; WLog_LVL(TAG, g_LogLevel, "GetStatusChangeW_Call {"); - smartcard_log_context(TAG, &call->hContext); + smartcard_log_context(TAG, &call->handles.hContext); WLog_LVL(TAG, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut, call->cReaders); @@ -580,7 +588,7 @@ mszGroupsA = smartcard_convert_string_list(call->mszGroups, call->cBytes, unicode); WLog_LVL(TAG, g_LogLevel, "ListReaders%s_Call {", unicode ? "W" : "A"); - smartcard_log_context(TAG, &call->hContext); + smartcard_log_context(TAG, &call->handles.hContext); WLog_LVL(TAG, g_LogLevel, "cBytes: %" PRIu32 " mszGroups: %s fmszReadersIsNULL: %" PRId32 @@ -604,7 +612,7 @@ return; WLog_LVL(TAG, g_LogLevel, "LocateCardsByATRA_Call {"); - smartcard_log_context(TAG, &call->hContext); + smartcard_log_context(TAG, &call->handles.hContext); for (index = 0; index < call->cReaders; index++) { @@ -641,7 +649,7 @@ return; WLog_LVL(TAG, g_LogLevel, "LocateCardsA_Call {"); - smartcard_log_context(TAG, &call->hContext); + smartcard_log_context(TAG, &call->handles.hContext); WLog_LVL(TAG, g_LogLevel, " cBytes=%" PRId32, call->cBytes); WLog_LVL(TAG, g_LogLevel, " mszCards=%s", smartcard_msz_dump_a(call->mszCards, call->cBytes, buffer, sizeof(buffer))); @@ -732,7 +740,7 @@ return; WLog_LVL(TAG, g_LogLevel, "LocateCardsW_Call {"); - smartcard_log_context(TAG, &call->hContext); + smartcard_log_context(TAG, &call->handles.hContext); WLog_LVL(TAG, g_LogLevel, " cBytes=%" PRId32, call->cBytes); WLog_LVL(TAG, g_LogLevel, " sz2=%s", smartcard_msz_dump_w(call->mszCards, call->cBytes, buffer, sizeof(buffer))); @@ -814,7 +822,7 @@ return; WLog_LVL(TAG, g_LogLevel, "ContextAndTwoStringW_Call {"); - smartcard_log_context(TAG, &call->hContext); + smartcard_log_context(TAG, &call->handles.hContext); WLog_LVL(TAG, g_LogLevel, " sz1=%s", call->sz1); WLog_LVL(TAG, g_LogLevel, " sz2=%s", call->sz2); WLog_LVL(TAG, g_LogLevel, "}"); @@ -831,7 +839,7 @@ return; WLog_LVL(TAG, g_LogLevel, "ContextAndTwoStringW_Call {"); - smartcard_log_context(TAG, &call->hContext); + smartcard_log_context(TAG, &call->handles.hContext); ConvertFromUnicode(CP_UTF8, 0, call->sz1, -1, &sz1, 0, NULL, NULL); ConvertFromUnicode(CP_UTF8, 0, call->sz2, -1, &sz2, 0, NULL, NULL); WLog_LVL(TAG, g_LogLevel, " sz1=%s", sz1); @@ -850,8 +858,8 @@ return; WLog_LVL(TAG, g_LogLevel, "GetTransmitCount_Call {"); - smartcard_log_context(TAG, &call->hContext); - smartcard_log_redir_handle(TAG, &call->hCard); + smartcard_log_context(TAG, &call->handles.hContext); + smartcard_log_redir_handle(TAG, &call->handles.hCard); WLog_LVL(TAG, g_LogLevel, "}"); } @@ -868,7 +876,7 @@ WLog_LVL(TAG, g_LogLevel, " szLookupName=%s", call->szLookupName); - smartcard_log_context(TAG, &call->Common.hContext); + smartcard_log_context(TAG, &call->Common.handles.hContext); WLog_DBG( TAG, "..CardIdentifier=%s", smartcard_array_dump(call->Common.CardIdentifier, sizeof(UUID), buffer, sizeof(buffer))); @@ -894,7 +902,7 @@ ConvertFromUnicode(CP_UTF8, 0, call->szLookupName, -1, &tmp, 0, NULL, NULL); WLog_LVL(TAG, g_LogLevel, " szLookupName=%s", tmp); free(tmp); - smartcard_log_context(TAG, &call->Common.hContext); + smartcard_log_context(TAG, &call->Common.handles.hContext); WLog_DBG( TAG, "..CardIdentifier=%s", smartcard_array_dump(call->Common.CardIdentifier, sizeof(UUID), buffer, sizeof(buffer))); @@ -917,7 +925,7 @@ WLog_LVL(TAG, g_LogLevel, "GetTransmitCount_Call {"); WLog_LVL(TAG, g_LogLevel, " szLookupName=%s", call->szLookupName); - smartcard_log_context(TAG, &call->Common.hContext); + smartcard_log_context(TAG, &call->Common.handles.hContext); WLog_DBG( TAG, "..CardIdentifier=%s", smartcard_array_dump(call->Common.CardIdentifier, sizeof(UUID), buffer, sizeof(buffer))); @@ -942,7 +950,7 @@ ConvertFromUnicode(CP_UTF8, 0, call->szLookupName, -1, &tmp, 0, NULL, NULL); WLog_LVL(TAG, g_LogLevel, " szLookupName=%s", tmp); free(tmp); - smartcard_log_context(TAG, &call->Common.hContext); + smartcard_log_context(TAG, &call->Common.handles.hContext); WLog_DBG( TAG, "..CardIdentifier=%s", smartcard_array_dump(call->Common.CardIdentifier, sizeof(UUID), buffer, sizeof(buffer))); @@ -963,8 +971,8 @@ return; WLog_LVL(TAG, g_LogLevel, "Transmit_Call {"); - smartcard_log_context(TAG, &call->hContext); - smartcard_log_redir_handle(TAG, &call->hCard); + smartcard_log_context(TAG, &call->handles.hContext); + smartcard_log_redir_handle(TAG, &call->handles.hCard); if (call->pioSendPci) { @@ -1036,7 +1044,7 @@ return; WLog_LVL(TAG, g_LogLevel, "LocateCardsByATRW_Call {"); - smartcard_log_context(TAG, &call->hContext); + smartcard_log_context(TAG, &call->handles.hContext); for (index = 0; index < call->cReaders; index++) { @@ -1151,8 +1159,8 @@ return; WLog_LVL(TAG, g_LogLevel, "Control_Call {"); - smartcard_log_context(TAG, &call->hContext); - smartcard_log_redir_handle(TAG, &call->hCard); + smartcard_log_context(TAG, &call->handles.hContext); + smartcard_log_redir_handle(TAG, &call->handles.hCard); WLog_LVL(TAG, g_LogLevel, "dwControlCode: 0x%08" PRIX32 " cbInBufferSize: %" PRIu32 @@ -1184,8 +1192,8 @@ return; WLog_LVL(TAG, g_LogLevel, "GetAttrib_Call {"); - smartcard_log_context(TAG, &call->hContext); - smartcard_log_redir_handle(TAG, &call->hCard); + smartcard_log_context(TAG, &call->handles.hContext); + smartcard_log_redir_handle(TAG, &call->handles.hCard); WLog_LVL(TAG, g_LogLevel, "dwAttrId: 0x%08" PRIX32, call->dwAttrId); WLog_LVL(TAG, g_LogLevel, "cbAttrLen: 0x%08" PRId32, call->cbAttrLen); WLog_LVL(TAG, g_LogLevel, "pbAttr: %s", @@ -1213,7 +1221,8 @@ } else if (dwAttrId == SCARD_ATTR_CURRENT_PROTOCOL_TYPE) { - union { + union + { BYTE* pb; DWORD* pd; } attr; @@ -1233,8 +1242,8 @@ return; WLog_LVL(TAG, g_LogLevel, "GetAttrib_Call {"); - smartcard_log_context(TAG, &call->hContext); - smartcard_log_redir_handle(TAG, &call->hCard); + smartcard_log_context(TAG, &call->handles.hContext); + smartcard_log_redir_handle(TAG, &call->handles.hCard); WLog_LVL(TAG, g_LogLevel, "dwAttrId: %s (0x%08" PRIX32 ") fpbAttrIsNULL: %" PRId32 " cbAttrLen: 0x%08" PRIX32 "", @@ -1252,8 +1261,8 @@ return; WLog_LVL(TAG, g_LogLevel, "Status%s_Call {", unicode ? "W" : "A"); - smartcard_log_context(TAG, &call->hContext); - smartcard_log_redir_handle(TAG, &call->hCard); + smartcard_log_context(TAG, &call->handles.hContext); + smartcard_log_redir_handle(TAG, &call->handles.hCard); WLog_LVL(TAG, g_LogLevel, "fmszReaderNamesIsNULL: %" PRId32 " cchReaderLen: %" PRIu32 " cbAtrLen: %" PRIu32 "", @@ -1266,13 +1275,18 @@ { char* mszReaderNamesA = NULL; char buffer[1024]; + DWORD cBytes; WINPR_UNUSED(smartcard); if (!WLog_IsLevelActive(WLog_Get(TAG), g_LogLevel)) return; - - mszReaderNamesA = smartcard_convert_string_list(ret->mszReaderNames, ret->cBytes, unicode); + cBytes = ret->cBytes; + if (ret->ReturnCode != SCARD_S_SUCCESS) + cBytes = 0; + if (cBytes == SCARD_AUTOALLOCATE) + cBytes = 0; + mszReaderNamesA = smartcard_convert_string_list(ret->mszReaderNames, cBytes, unicode); WLog_LVL(TAG, g_LogLevel, "Status%s_Return {", unicode ? "W" : "A"); WLog_LVL(TAG, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")", @@ -1334,7 +1348,7 @@ return; WLog_LVL(TAG, g_LogLevel, "ConnectA_Call {"); - smartcard_log_context(TAG, &call->Common.hContext); + smartcard_log_context(TAG, &call->Common.handles.hContext); WLog_LVL(TAG, g_LogLevel, "szReader: %s dwShareMode: %s (0x%08" PRIX32 ") dwPreferredProtocols: %s (0x%08" PRIX32 @@ -1355,7 +1369,7 @@ ConvertFromUnicode(CP_UTF8, 0, call->szReader, -1, &szReaderA, 0, NULL, NULL); WLog_LVL(TAG, g_LogLevel, "ConnectW_Call {"); - smartcard_log_context(TAG, &call->Common.hContext); + smartcard_log_context(TAG, &call->Common.handles.hContext); WLog_LVL(TAG, g_LogLevel, "szReader: %s dwShareMode: %s (0x%08" PRIX32 ") dwPreferredProtocols: %s (0x%08" PRIX32 @@ -1377,8 +1391,8 @@ return; WLog_LVL(TAG, g_LogLevel, "%s_Call {", name); - smartcard_log_context(TAG, &call->hContext); - smartcard_log_redir_handle(TAG, &call->hCard); + smartcard_log_context(TAG, &call->handles.hContext); + smartcard_log_redir_handle(TAG, &call->handles.hCard); WLog_LVL(TAG, g_LogLevel, "dwDisposition: %s (0x%08" PRIX32 ")", SCardGetDispositionString(call->dwDisposition), call->dwDisposition); @@ -1455,8 +1469,8 @@ return; WLog_LVL(TAG, g_LogLevel, "Reconnect_Call {"); - smartcard_log_context(TAG, &call->hContext); - smartcard_log_redir_handle(TAG, &call->hCard); + smartcard_log_context(TAG, &call->handles.hContext); + smartcard_log_redir_handle(TAG, &call->handles.hCard); WLog_LVL(TAG, g_LogLevel, "dwShareMode: %s (0x%08" PRIX32 ") dwPreferredProtocols: %s (0x%08" PRIX32 @@ -1706,6 +1720,9 @@ SCARDHANDLE hCard = 0; WINPR_UNUSED(smartcard); + if (handle->cbHandle == 0) + return hCard; + if (handle->cbHandle != sizeof(ULONG_PTR)) { WLog_WARN(TAG, @@ -2000,11 +2017,12 @@ LONG status; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "", status); @@ -2017,7 +2035,7 @@ { LONG status; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; @@ -2030,7 +2048,7 @@ Stream_Read_INT32(s, call->fmszGroupsIsNULL); /* fmszGroupsIsNULL (4 bytes) */ Stream_Read_UINT32(s, call->cchGroups); /* cchGroups (4 bytes) */ - status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)); + status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)); if (status != SCARD_S_SUCCESS) return status; @@ -2042,22 +2060,27 @@ LONG smartcard_pack_list_reader_groups_return(SMARTCARD_DEVICE* smartcard, wStream* s, const ListReaderGroups_Return* ret, BOOL unicode) { + LONG status; + DWORD cBytes = ret->cBytes; DWORD index = 0; - UINT32 size = unicode ? sizeof(WCHAR) : sizeof(CHAR); - size *= ret->cBytes; smartcard_trace_list_reader_groups_return(smartcard, ret, unicode); if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; + cBytes = 0; + if (cBytes == SCARD_AUTOALLOCATE) + cBytes = 0; if (!Stream_EnsureRemainingCapacity(s, 4)) return SCARD_E_NO_MEMORY; - Stream_Write_UINT32(s, size); /* cBytes (4 bytes) */ - if (!smartcard_ndr_pointer_write(s, &index, size)) + Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */ + if (!smartcard_ndr_pointer_write(s, &index, cBytes)) return SCARD_E_NO_MEMORY; - return smartcard_ndr_write(s, ret->msz, size, 1, NDR_PTR_SIMPLE); + status = smartcard_ndr_write(s, ret->msz, cBytes, 1, NDR_PTR_SIMPLE); + if (status != SCARD_S_SUCCESS) + return status; + return ret->ReturnCode; } LONG smartcard_unpack_list_readers_call(SMARTCARD_DEVICE* smartcard, wStream* s, @@ -2068,7 +2091,7 @@ UINT32 mszGroupsNdrPtr; call->mszGroups = NULL; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; @@ -2084,7 +2107,8 @@ Stream_Read_INT32(s, call->fmszReadersIsNULL); /* fmszReadersIsNULL (4 bytes) */ Stream_Read_UINT32(s, call->cchReaders); /* cchReaders (4 bytes) */ - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; if (mszGroupsNdrPtr) @@ -2101,6 +2125,7 @@ LONG smartcard_pack_list_readers_return(SMARTCARD_DEVICE* smartcard, wStream* s, const ListReaders_Return* ret, BOOL unicode) { + LONG status; DWORD index = 0; UINT32 size = unicode ? sizeof(WCHAR) : sizeof(CHAR); @@ -2108,7 +2133,7 @@ smartcard_trace_list_readers_return(smartcard, ret, unicode); if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; + size = 0; if (!Stream_EnsureRemainingCapacity(s, 4)) { @@ -2120,15 +2145,18 @@ if (!smartcard_ndr_pointer_write(s, &index, size)) return SCARD_E_NO_MEMORY; - return smartcard_ndr_write(s, ret->msz, size, 1, NDR_PTR_SIMPLE); + status = smartcard_ndr_write(s, ret->msz, size, 1, NDR_PTR_SIMPLE); + if (status != SCARD_S_SUCCESS) + return status; + return ret->ReturnCode; } static LONG smartcard_unpack_connect_common(SMARTCARD_DEVICE* smartcard, wStream* s, - Connect_Common* common, UINT32* index) + Connect_Common_Call* common, UINT32* index) { LONG status; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(common->hContext), index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(common->handles.hContext), index); if (status != SCARD_S_SUCCESS) return status; @@ -2162,7 +2190,8 @@ if (status != SCARD_S_SUCCESS) return status; - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->Common.hContext)))) + if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, + &(call->Common.handles.hContext)))) WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "", status); @@ -2190,7 +2219,8 @@ if (status != SCARD_S_SUCCESS) return status; - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->Common.hContext)))) + if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, + &(call->Common.handles.hContext)))) WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "", status); @@ -2205,8 +2235,6 @@ DWORD index = 0; smartcard_trace_connect_return(smartcard, ret); - if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; status = smartcard_pack_redir_scard_context(smartcard, s, &ret->hContext, &index); if (status != SCARD_S_SUCCESS) @@ -2231,11 +2259,11 @@ LONG status; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; - status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard), &index); + status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->handles.hCard), &index); if (status != SCARD_S_SUCCESS) return status; @@ -2249,14 +2277,15 @@ Stream_Read_UINT32(s, call->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */ Stream_Read_UINT32(s, call->dwInitialization); /* dwInitialization (4 bytes) */ - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) { WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "", status); return status; } - if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard)))) + if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->handles.hCard)))) WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status); @@ -2268,13 +2297,11 @@ const Reconnect_Return* ret) { smartcard_trace_reconnect_return(smartcard, ret); - if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; if (!Stream_EnsureRemainingCapacity(s, 4)) return SCARD_E_NO_MEMORY; Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */ - return SCARD_S_SUCCESS; + return ret->ReturnCode; } LONG smartcard_unpack_hcard_and_disposition_call(SMARTCARD_DEVICE* smartcard, wStream* s, @@ -2283,11 +2310,11 @@ LONG status; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; - status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard), &index); + status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->handles.hCard), &index); if (status != SCARD_S_SUCCESS) return status; @@ -2300,10 +2327,11 @@ Stream_Read_UINT32(s, call->dwDisposition); /* dwDisposition (4 bytes) */ - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; - if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard)))) + if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->handles.hCard)))) return status; smartcard_trace_hcard_and_disposition_call(smartcard, call, name); @@ -2323,7 +2351,7 @@ return; WLog_LVL(TAG, g_LogLevel, "GetStatusChangeA_Call {"); - smartcard_log_context(TAG, &call->hContext); + smartcard_log_context(TAG, &call->handles.hContext); WLog_LVL(TAG, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut, call->cReaders); @@ -2350,8 +2378,9 @@ UINT32 cReaders, UINT32* ptrIndex) { UINT32 index, len; - LONG status = ERROR_INVALID_DATA; + LONG status = SCARD_E_NO_MEMORY; LPSCARD_READERSTATEA rgReaderStates; + BOOL* states; if (Stream_GetRemainingLength(s) < 4) return status; @@ -2363,12 +2392,14 @@ return status; } rgReaderStates = (LPSCARD_READERSTATEA)calloc(cReaders, sizeof(SCARD_READERSTATEA)); - - if (!rgReaderStates) - return STATUS_NO_MEMORY; + states = calloc(cReaders, sizeof(BOOL)); + if (!rgReaderStates || !states) + goto fail; + status = ERROR_INVALID_DATA; for (index = 0; index < cReaders; index++) { + UINT32 ptr = UINT32_MAX; LPSCARD_READERSTATEA readerState = &rgReaderStates[index]; if (Stream_GetRemainingLength(s) < 52) @@ -2378,8 +2409,13 @@ goto fail; } - if (!smartcard_ndr_pointer_read(s, ptrIndex, NULL)) - goto fail; + if (!smartcard_ndr_pointer_read(s, ptrIndex, &ptr)) + { + if (ptr != 0) + goto fail; + } + /* Ignore NULL length strings */ + states[index] = ptr != 0; Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */ Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */ Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */ @@ -2390,12 +2426,16 @@ { LPSCARD_READERSTATEA readerState = &rgReaderStates[index]; + /* Ignore empty strings */ + if (!states[index]) + continue; status = smartcard_ndr_read_a(s, &readerState->szReader, NDR_PTR_FULL); if (status != SCARD_S_SUCCESS) goto fail; } *ppcReaders = rgReaderStates; + free(states); return SCARD_S_SUCCESS; fail: if (rgReaderStates) @@ -2407,6 +2447,7 @@ } } free(rgReaderStates); + free(states); return status; } @@ -2414,8 +2455,9 @@ UINT32 cReaders, UINT32* ptrIndex) { UINT32 index, len; - LONG status = ERROR_INVALID_DATA; + LONG status = SCARD_E_NO_MEMORY; LPSCARD_READERSTATEW rgReaderStates; + BOOL* states; if (Stream_GetRemainingLength(s) < 4) return status; @@ -2428,12 +2470,15 @@ } rgReaderStates = (LPSCARD_READERSTATEW)calloc(cReaders, sizeof(SCARD_READERSTATEW)); + states = calloc(cReaders, sizeof(BOOL)); - if (!rgReaderStates) - return STATUS_NO_MEMORY; + if (!rgReaderStates || !states) + goto fail; + status = ERROR_INVALID_DATA; for (index = 0; index < cReaders; index++) { + UINT32 ptr = UINT32_MAX; LPSCARD_READERSTATEW readerState = &rgReaderStates[index]; if (Stream_GetRemainingLength(s) < 52) @@ -2443,8 +2488,13 @@ goto fail; } - if (!smartcard_ndr_pointer_read(s, ptrIndex, NULL)) - goto fail; + if (!smartcard_ndr_pointer_read(s, ptrIndex, &ptr)) + { + if (ptr != 0) + goto fail; + } + /* Ignore NULL length strings */ + states[index] = ptr != 0; Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */ Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */ Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */ @@ -2455,12 +2505,17 @@ { LPSCARD_READERSTATEW readerState = &rgReaderStates[index]; + /* Skip NULL pointers */ + if (!states[index]) + continue; + status = smartcard_ndr_read_w(s, &readerState->szReader, NDR_PTR_FULL); if (status != SCARD_S_SUCCESS) goto fail; } *ppcReaders = rgReaderStates; + free(states); return SCARD_S_SUCCESS; fail: if (rgReaderStates) @@ -2472,6 +2527,7 @@ } } free(rgReaderStates); + free(states); return status; } @@ -2487,7 +2543,7 @@ UINT32 index = 0; call->rgReaderStates = NULL; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; @@ -2503,7 +2559,8 @@ if (!smartcard_ndr_pointer_read(s, &index, &ndrPtr)) return ERROR_INVALID_DATA; - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; if (ndrPtr) @@ -2526,7 +2583,7 @@ call->rgReaderStates = NULL; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; @@ -2537,12 +2594,13 @@ return STATUS_BUFFER_TOO_SMALL; } - Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */ - Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */ + Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */ + Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */ if (!smartcard_ndr_pointer_read(s, &index, &ndrPtr)) return ERROR_INVALID_DATA; - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; if (ndrPtr) @@ -2559,19 +2617,26 @@ LONG smartcard_pack_get_status_change_return(SMARTCARD_DEVICE* smartcard, wStream* s, const GetStatusChange_Return* ret, BOOL unicode) { + LONG status; + DWORD cReaders = ret->cReaders; UINT32 index = 0; smartcard_trace_get_status_change_return(smartcard, ret, unicode); if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; + cReaders = 0; + if (cReaders == SCARD_AUTOALLOCATE) + cReaders = 0; if (!Stream_EnsureRemainingCapacity(s, 4)) return SCARD_E_NO_MEMORY; - Stream_Write_UINT32(s, ret->cReaders); /* cReaders (4 bytes) */ - if (!smartcard_ndr_pointer_write(s, &index, ret->cReaders)) + Stream_Write_UINT32(s, cReaders); /* cReaders (4 bytes) */ + if (!smartcard_ndr_pointer_write(s, &index, cReaders)) return SCARD_E_NO_MEMORY; - return smartcard_ndr_write_state(s, ret->rgReaderStates, ret->cReaders, NDR_PTR_SIMPLE); + status = smartcard_ndr_write_state(s, ret->rgReaderStates, cReaders, NDR_PTR_SIMPLE); + if (status != SCARD_S_SUCCESS) + return status; + return ret->ReturnCode; } LONG smartcard_unpack_state_call(SMARTCARD_DEVICE* smartcard, wStream* s, State_Call* call) @@ -2579,11 +2644,11 @@ LONG status; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; - status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard), &index); + status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->handles.hCard), &index); if (status != SCARD_S_SUCCESS) return status; @@ -2596,10 +2661,11 @@ Stream_Read_INT32(s, call->fpbAtrIsNULL); /* fpbAtrIsNULL (4 bytes) */ Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */ - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; - if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard)))) + if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->handles.hCard)))) return status; return status; @@ -2607,18 +2673,25 @@ LONG smartcard_pack_state_return(SMARTCARD_DEVICE* smartcard, wStream* s, const State_Return* ret) { + LONG status; + DWORD cbAtrLen = ret->cbAtrLen; DWORD index = 0; smartcard_trace_state_return(smartcard, ret); if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; + cbAtrLen = 0; + if (cbAtrLen == SCARD_AUTOALLOCATE) + cbAtrLen = 0; - Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */ - Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */ - Stream_Write_UINT32(s, ret->cbAtrLen); /* cbAtrLen (4 bytes) */ - if (!smartcard_ndr_pointer_write(s, &index, ret->cbAtrLen)) + Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */ + Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */ + Stream_Write_UINT32(s, cbAtrLen); /* cbAtrLen (4 bytes) */ + if (!smartcard_ndr_pointer_write(s, &index, cbAtrLen)) return SCARD_E_NO_MEMORY; - return smartcard_ndr_write(s, ret->rgAtr, ret->cbAtrLen, 1, NDR_PTR_SIMPLE); + status = smartcard_ndr_write(s, ret->rgAtr, cbAtrLen, 1, NDR_PTR_SIMPLE); + if (status != SCARD_S_SUCCESS) + return status; + return ret->ReturnCode; } LONG smartcard_unpack_status_call(SMARTCARD_DEVICE* smartcard, wStream* s, Status_Call* call, @@ -2626,11 +2699,11 @@ { LONG status; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; - status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard), &index); + status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->handles.hCard), &index); if (status != SCARD_S_SUCCESS) return status; @@ -2644,10 +2717,11 @@ Stream_Read_UINT32(s, call->cchReaderLen); /* cchReaderLen (4 bytes) */ Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */ - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; - if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard)))) + if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->handles.hCard)))) return status; smartcard_trace_status_call(smartcard, call, unicode); @@ -2657,29 +2731,34 @@ LONG smartcard_pack_status_return(SMARTCARD_DEVICE* smartcard, wStream* s, const Status_Return* ret, BOOL unicode) { + LONG status; DWORD index = 0; - UINT32 size = unicode ? sizeof(WCHAR) : sizeof(CHAR); - size *= ret->cBytes; + DWORD cBytes = ret->cBytes; smartcard_trace_status_return(smartcard, ret, unicode); if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; + cBytes = 0; + if (cBytes == SCARD_AUTOALLOCATE) + cBytes = 0; if (!Stream_EnsureRemainingCapacity(s, 4)) return SCARD_F_INTERNAL_ERROR; - Stream_Write_UINT32(s, size); /* cBytes (4 bytes) */ - if (!smartcard_ndr_pointer_write(s, &index, size)) + Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */ + if (!smartcard_ndr_pointer_write(s, &index, cBytes)) return SCARD_E_NO_MEMORY; if (!Stream_EnsureRemainingCapacity(s, 44)) return SCARD_F_INTERNAL_ERROR; - Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */ - Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */ + Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */ + Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */ Stream_Write(s, ret->pbAtr, sizeof(ret->pbAtr)); /* pbAtr (32 bytes) */ - Stream_Write_UINT32(s, ret->cbAtrLen); /* cbAtrLen (4 bytes) */ - return smartcard_ndr_write(s, ret->mszReaderNames, size, 1, NDR_PTR_SIMPLE); + Stream_Write_UINT32(s, ret->cbAtrLen); /* cbAtrLen (4 bytes) */ + status = smartcard_ndr_write(s, ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE); + if (status != SCARD_S_SUCCESS) + return status; + return ret->ReturnCode; } LONG smartcard_unpack_get_attrib_call(SMARTCARD_DEVICE* smartcard, wStream* s, GetAttrib_Call* call) @@ -2687,11 +2766,11 @@ LONG status; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; - status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard), &index); + status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->handles.hCard), &index); if (status != SCARD_S_SUCCESS) return status; @@ -2705,10 +2784,11 @@ Stream_Read_INT32(s, call->fpbAttrIsNULL); /* fpbAttrIsNULL (4 bytes) */ Stream_Read_UINT32(s, call->cbAttrLen); /* cbAttrLen (4 bytes) */ - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; - if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard)))) + if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->handles.hCard)))) return status; smartcard_trace_get_attrib_call(smartcard, call); @@ -2716,21 +2796,32 @@ } 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 status; + DWORD cbAttrLen; DWORD index = 0; smartcard_trace_get_attrib_return(smartcard, ret, dwAttrId); - if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; if (!Stream_EnsureRemainingCapacity(s, 4)) return SCARD_F_INTERNAL_ERROR; - Stream_Write_UINT32(s, ret->cbAttrLen); /* cbAttrLen (4 bytes) */ - if (!smartcard_ndr_pointer_write(s, &index, ret->cbAttrLen)) + cbAttrLen = ret->cbAttrLen; + if (ret->ReturnCode != SCARD_S_SUCCESS) + cbAttrLen = 0; + if (cbAttrLen == SCARD_AUTOALLOCATE) + cbAttrLen = 0; + if (cbAttrCallLen < cbAttrLen) + cbAttrLen = cbAttrCallLen; + Stream_Write_UINT32(s, cbAttrLen); /* cbAttrLen (4 bytes) */ + if (!smartcard_ndr_pointer_write(s, &index, cbAttrLen)) return SCARD_E_NO_MEMORY; - return smartcard_ndr_write(s, ret->pbAttr, ret->cbAttrLen, 1, NDR_PTR_SIMPLE); + status = smartcard_ndr_write(s, ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE); + if (status != SCARD_S_SUCCESS) + return status; + return ret->ReturnCode; } LONG smartcard_unpack_control_call(SMARTCARD_DEVICE* smartcard, wStream* s, Control_Call* call) @@ -2741,11 +2832,11 @@ call->pvInBuffer = NULL; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; - status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard), &index); + status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->handles.hCard), &index); if (status != SCARD_S_SUCCESS) return status; @@ -2755,17 +2846,18 @@ return STATUS_BUFFER_TOO_SMALL; } - Stream_Read_UINT32(s, call->dwControlCode); /* dwControlCode (4 bytes) */ - Stream_Read_UINT32(s, call->cbInBufferSize); /* cbInBufferSize (4 bytes) */ + Stream_Read_UINT32(s, call->dwControlCode); /* dwControlCode (4 bytes) */ + Stream_Read_UINT32(s, call->cbInBufferSize); /* cbInBufferSize (4 bytes) */ if (!smartcard_ndr_pointer_read(s, &index, &pvInBufferNdrPtr)) /* pvInBufferNdrPtr (4 bytes) */ return ERROR_INVALID_DATA; Stream_Read_INT32(s, call->fpvOutBufferIsNULL); /* fpvOutBufferIsNULL (4 bytes) */ Stream_Read_UINT32(s, call->cbOutBufferSize); /* cbOutBufferSize (4 bytes) */ - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; - if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard)))) + if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->handles.hCard)))) return status; if (pvInBufferNdrPtr) @@ -2782,20 +2874,27 @@ LONG smartcard_pack_control_return(SMARTCARD_DEVICE* smartcard, wStream* s, const Control_Return* ret) { + LONG status; + DWORD cbDataLen = ret->cbOutBufferSize; DWORD index = 0; smartcard_trace_control_return(smartcard, ret); if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; + cbDataLen = 0; + if (cbDataLen == SCARD_AUTOALLOCATE) + cbDataLen = 0; if (!Stream_EnsureRemainingCapacity(s, 4)) return SCARD_F_INTERNAL_ERROR; - Stream_Write_UINT32(s, ret->cbOutBufferSize); /* cbOutBufferSize (4 bytes) */ - if (!smartcard_ndr_pointer_write(s, &index, ret->cbOutBufferSize)) + Stream_Write_UINT32(s, cbDataLen); /* cbOutBufferSize (4 bytes) */ + if (!smartcard_ndr_pointer_write(s, &index, cbDataLen)) return SCARD_E_NO_MEMORY; - return smartcard_ndr_write(s, ret->pvOutBuffer, ret->cbOutBufferSize, 1, NDR_PTR_SIMPLE); + status = smartcard_ndr_write(s, ret->pvOutBuffer, cbDataLen, 1, NDR_PTR_SIMPLE); + if (status != SCARD_S_SUCCESS) + return status; + return ret->ReturnCode; } LONG smartcard_unpack_transmit_call(SMARTCARD_DEVICE* smartcard, wStream* s, Transmit_Call* call) @@ -2813,11 +2912,11 @@ call->pioRecvPci = NULL; call->pbSendBuffer = NULL; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; - status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard), &index); + status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->handles.hCard), &index); if (status != SCARD_S_SUCCESS) return status; @@ -2828,13 +2927,13 @@ return STATUS_BUFFER_TOO_SMALL; } - Stream_Read_UINT32(s, ioSendPci.dwProtocol); /* dwProtocol (4 bytes) */ - Stream_Read_UINT32(s, ioSendPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */ + Stream_Read_UINT32(s, ioSendPci.dwProtocol); /* dwProtocol (4 bytes) */ + Stream_Read_UINT32(s, ioSendPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */ if (!smartcard_ndr_pointer_read(s, &index, &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */ return ERROR_INVALID_DATA; - Stream_Read_UINT32(s, call->cbSendLength); /* cbSendLength (4 bytes) */ + Stream_Read_UINT32(s, call->cbSendLength); /* cbSendLength (4 bytes) */ if (!smartcard_ndr_pointer_read(s, &index, &pbSendBufferNdrPtr)) /* pbSendBufferNdrPtr (4 bytes) */ return ERROR_INVALID_DATA; @@ -2860,10 +2959,11 @@ return STATUS_INVALID_PARAMETER; } - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; - if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard)))) + if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->handles.hCard)))) return status; if (ioSendPci.cbExtraBytes && !pbExtraBytesNdrPtr) @@ -3032,14 +3132,13 @@ LONG smartcard_pack_transmit_return(SMARTCARD_DEVICE* smartcard, wStream* s, const Transmit_Return* ret) { + LONG status; DWORD index = 0; LONG error; UINT32 cbRecvLength = ret->cbRecvLength; UINT32 cbRecvPci = ret->pioRecvPci ? ret->pioRecvPci->cbPciLength : 0; smartcard_trace_transmit_return(smartcard, ret); - if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; if (!ret->pbRecvBuffer) cbRecvLength = 0; @@ -3072,7 +3171,10 @@ return error; } - return smartcard_ndr_write(s, ret->pbRecvBuffer, ret->cbRecvLength, 1, NDR_PTR_SIMPLE); + status = smartcard_ndr_write(s, ret->pbRecvBuffer, ret->cbRecvLength, 1, NDR_PTR_SIMPLE); + if (status != SCARD_S_SUCCESS) + return status; + return ret->ReturnCode; } LONG smartcard_unpack_locate_cards_by_atr_a_call(SMARTCARD_DEVICE* smartcard, wStream* s, @@ -3084,7 +3186,7 @@ UINT32 index = 0; call->rgReaderStates = NULL; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; @@ -3102,7 +3204,8 @@ if (!smartcard_ndr_pointer_read(s, &index, &rgReaderStatesNdrPtr)) return ERROR_INVALID_DATA; - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs)) @@ -3139,7 +3242,7 @@ UINT32 sz1NdrPtr, sz2NdrPtr; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; @@ -3148,7 +3251,7 @@ if (!smartcard_ndr_pointer_read(s, &index, &sz2NdrPtr)) return ERROR_INVALID_DATA; - status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->hContext); + status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->handles.hContext); if (status != SCARD_S_SUCCESS) return status; @@ -3174,7 +3277,7 @@ LONG status; UINT32 sz1NdrPtr, sz2NdrPtr; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; @@ -3183,7 +3286,7 @@ if (!smartcard_ndr_pointer_read(s, &index, &sz2NdrPtr)) return ERROR_INVALID_DATA; - status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->hContext); + status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->handles.hContext); if (status != SCARD_S_SUCCESS) return status; @@ -3209,7 +3312,7 @@ LONG status; UINT32 sz1NdrPtr, sz2NdrPtr; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; @@ -3250,7 +3353,7 @@ UINT32 sz1NdrPtr, sz2NdrPtr; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; @@ -3290,10 +3393,10 @@ UINT32 index = 0; UINT32 ndrPtr; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; - status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard), &index); + status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->handles.hCard), &index); if (status != SCARD_S_SUCCESS) return status; @@ -3302,14 +3405,15 @@ Stream_Read_UINT32(s, call->dwAttrId); Stream_Read_UINT32(s, call->cbAttrLen); - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) - return status; + if (!smartcard_ndr_pointer_read(s, &index, &ndrPtr)) + return ERROR_INVALID_DATA; - if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; - if (!smartcard_ndr_pointer_read(s, &index, &ndrPtr)) - return ERROR_INVALID_DATA; + if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->handles.hCard)))) + return status; if (ndrPtr) { @@ -3332,7 +3436,7 @@ UINT32 index = 0; call->rgReaderStates = NULL; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; @@ -3347,11 +3451,12 @@ if (!smartcard_ndr_pointer_read(s, &index, &rgAtrMasksNdrPtr)) return ERROR_INVALID_DATA; - Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */ + Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */ if (!smartcard_ndr_pointer_read(s, &index, &rgReaderStatesNdrPtr)) return ERROR_INVALID_DATA; - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) return status; if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs)) @@ -3392,7 +3497,8 @@ if (!smartcard_ndr_pointer_read(s, &index, &mszNdrPtr)) return ERROR_INVALID_DATA; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->Common.hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->Common.handles.hContext), + &index); if (status != SCARD_S_SUCCESS) return status; @@ -3413,7 +3519,7 @@ return status; } - status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->Common.hContext); + status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->Common.handles.hContext); if (status != SCARD_S_SUCCESS) return status; @@ -3438,7 +3544,8 @@ if (!smartcard_ndr_pointer_read(s, &index, &mszNdrPtr)) return ERROR_INVALID_DATA; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->Common.hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->Common.handles.hContext), + &index); if (status != SCARD_S_SUCCESS) return status; @@ -3459,7 +3566,7 @@ return status; } - status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->Common.hContext); + status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->Common.handles.hContext); if (status != SCARD_S_SUCCESS) return status; @@ -3485,7 +3592,8 @@ if (!smartcard_ndr_pointer_read(s, &index, &mszNdrPtr)) return ERROR_INVALID_DATA; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->Common.hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->Common.handles.hContext), + &index); if (status != SCARD_S_SUCCESS) return status; @@ -3509,7 +3617,7 @@ return status; } - status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->Common.hContext); + status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->Common.handles.hContext); if (status != SCARD_S_SUCCESS) return status; @@ -3545,7 +3653,8 @@ if (!smartcard_ndr_pointer_read(s, &index, &mszNdrPtr)) return ERROR_INVALID_DATA; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->Common.hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->Common.handles.hContext), + &index); if (status != SCARD_S_SUCCESS) return status; @@ -3568,7 +3677,7 @@ return status; } - status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->Common.hContext); + status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &call->Common.handles.hContext); if (status != SCARD_S_SUCCESS) return status; @@ -3598,22 +3707,23 @@ LONG status; UINT32 index = 0; - status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->hContext), &index); + status = smartcard_unpack_redir_scard_context(smartcard, s, &(call->handles.hContext), &index); if (status != SCARD_S_SUCCESS) return status; - status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->hCard), &index); + status = smartcard_unpack_redir_scard_handle(smartcard, s, &(call->handles.hCard), &index); if (status != SCARD_S_SUCCESS) return status; - if ((status = smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->hContext)))) + if ((status = + smartcard_unpack_redir_scard_context_ref(smartcard, s, &(call->handles.hContext)))) { WLog_ERR(TAG, "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "", status); return status; } - if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->hCard)))) + if ((status = smartcard_unpack_redir_scard_handle_ref(smartcard, s, &(call->handles.hCard)))) WLog_ERR(TAG, "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status); @@ -3624,26 +3734,28 @@ LONG smartcard_unpack_get_reader_icon_call(SMARTCARD_DEVICE* smartcard, wStream* s, GetReaderIcon_Call* call) { - return smartcard_unpack_common_context_and_string_w(smartcard, s, &call->hContext, + return smartcard_unpack_common_context_and_string_w(smartcard, s, &call->handles.hContext, &call->szReaderName); } LONG smartcard_unpack_context_and_string_a_call(SMARTCARD_DEVICE* smartcard, wStream* s, ContextAndStringA_Call* call) { - return smartcard_unpack_common_context_and_string_a(smartcard, s, &call->hContext, &call->sz); + return smartcard_unpack_common_context_and_string_a(smartcard, s, &call->handles.hContext, + &call->sz); } LONG smartcard_unpack_context_and_string_w_call(SMARTCARD_DEVICE* smartcard, wStream* s, ContextAndStringW_Call* call) { - return smartcard_unpack_common_context_and_string_w(smartcard, s, &call->hContext, &call->sz); + return smartcard_unpack_common_context_and_string_w(smartcard, s, &call->handles.hContext, + &call->sz); } LONG smartcard_unpack_get_device_type_id_call(SMARTCARD_DEVICE* smartcard, wStream* s, GetDeviceTypeId_Call* call) { - return smartcard_unpack_common_context_and_string_w(smartcard, s, &call->hContext, + return smartcard_unpack_common_context_and_string_w(smartcard, s, &call->handles.hContext, &call->szReaderName); } @@ -3651,8 +3763,6 @@ const GetDeviceTypeId_Return* ret) { smartcard_trace_device_type_id_return(smartcard, ret); - if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; if (!Stream_EnsureRemainingCapacity(s, 4)) { @@ -3662,16 +3772,21 @@ Stream_Write_UINT32(s, ret->dwDeviceId); /* cBytes (4 bytes) */ - return SCARD_S_SUCCESS; + return ret->ReturnCode; } LONG smartcard_pack_locate_cards_return(SMARTCARD_DEVICE* smartcard, wStream* s, const LocateCards_Return* ret) { + LONG status; + DWORD cbDataLen = ret->cReaders; DWORD index = 0; + smartcard_trace_locate_cards_return(smartcard, ret); if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; + cbDataLen = 0; + if (cbDataLen == SCARD_AUTOALLOCATE) + cbDataLen = 0; if (!Stream_EnsureRemainingCapacity(s, 4)) { @@ -3679,20 +3794,27 @@ return SCARD_F_INTERNAL_ERROR; } - Stream_Write_UINT32(s, ret->cReaders); /* cBytes (4 cbDataLen) */ - if (!smartcard_ndr_pointer_write(s, &index, ret->cReaders)) + Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */ + if (!smartcard_ndr_pointer_write(s, &index, cbDataLen)) return SCARD_E_NO_MEMORY; - return smartcard_ndr_write_state(s, ret->rgReaderStates, ret->cReaders, NDR_PTR_SIMPLE); + status = smartcard_ndr_write_state(s, ret->rgReaderStates, cbDataLen, NDR_PTR_SIMPLE); + if (status != SCARD_S_SUCCESS) + return status; + return ret->ReturnCode; } LONG smartcard_pack_get_reader_icon_return(SMARTCARD_DEVICE* smartcard, wStream* s, const GetReaderIcon_Return* ret) { + LONG status; DWORD index = 0; + DWORD cbDataLen = ret->cbDataLen; smartcard_trace_get_reader_icon_return(smartcard, ret); if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; + cbDataLen = 0; + if (cbDataLen == SCARD_AUTOALLOCATE) + cbDataLen = 0; if (!Stream_EnsureRemainingCapacity(s, 4)) { @@ -3700,19 +3822,20 @@ return SCARD_F_INTERNAL_ERROR; } - Stream_Write_UINT32(s, ret->cbDataLen); /* cBytes (4 cbDataLen) */ - if (!smartcard_ndr_pointer_write(s, &index, ret->cbDataLen)) + Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */ + if (!smartcard_ndr_pointer_write(s, &index, cbDataLen)) return SCARD_E_NO_MEMORY; - return smartcard_ndr_write(s, ret->pbData, ret->cbDataLen, 1, NDR_PTR_SIMPLE); + status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE); + if (status != SCARD_S_SUCCESS) + return status; + return ret->ReturnCode; } LONG smartcard_pack_get_transmit_count_return(SMARTCARD_DEVICE* smartcard, wStream* s, const GetTransmitCount_Return* ret) { smartcard_trace_get_transmit_count_return(smartcard, ret); - if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; if (!Stream_EnsureRemainingCapacity(s, 4)) { @@ -3722,17 +3845,21 @@ Stream_Write_UINT32(s, ret->cTransmitCount); /* cBytes (4 cbDataLen) */ - return SCARD_S_SUCCESS; + return ret->ReturnCode; } LONG smartcard_pack_read_cache_return(SMARTCARD_DEVICE* smartcard, wStream* s, const ReadCache_Return* ret) { + LONG status; DWORD index = 0; - + DWORD cbDataLen = ret->cbDataLen; smartcard_trace_read_cache_return(smartcard, ret); if (ret->ReturnCode != SCARD_S_SUCCESS) - return ret->ReturnCode; + cbDataLen = 0; + + if (cbDataLen == SCARD_AUTOALLOCATE) + cbDataLen = 0; if (!Stream_EnsureRemainingCapacity(s, 4)) { @@ -3740,9 +3867,12 @@ return SCARD_F_INTERNAL_ERROR; } - Stream_Write_UINT32(s, ret->cbDataLen); /* cBytes (4 cbDataLen) */ - if (!smartcard_ndr_pointer_write(s, &index, ret->cbDataLen)) + Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */ + if (!smartcard_ndr_pointer_write(s, &index, cbDataLen)) return SCARD_E_NO_MEMORY; - return smartcard_ndr_write(s, ret->pbData, ret->cbDataLen, 1, NDR_PTR_SIMPLE); + status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE); + if (status != SCARD_S_SUCCESS) + return status; + return ret->ReturnCode; } diff -Nru freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_pack.h freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_pack.h --- freerdp2-2.2.0+dfsg1/channels/smartcard/client/smartcard_pack.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/smartcard/client/smartcard_pack.h 2021-02-25 08:51:41.000000000 +0000 @@ -28,420 +28,6 @@ #include #include -#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 @@ 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); diff -Nru freerdp2-2.2.0+dfsg1/channels/urbdrc/client/data_transfer.c freerdp2-2.3.0+dfsg1/channels/urbdrc/client/data_transfer.c --- freerdp2-2.2.0+dfsg1/channels/urbdrc/client/data_transfer.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/urbdrc/client/data_transfer.c 2021-02-25 08:51:41.000000000 +0000 @@ -242,7 +242,7 @@ 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 @@ 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 @@ 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 @@ 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); } } diff -Nru freerdp2-2.2.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.c freerdp2-2.3.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.c --- freerdp2-2.2.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.c 2021-02-25 08:51:41.000000000 +0000 @@ -75,12 +75,61 @@ 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 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 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ "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 @@ 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); - - if (!id1) - return -1; + ArrayList_Lock(pdev->request_queue); + transfer = list_contains(pdev->request_queue, cancelID1); + if (!transfer) + transfer = list_contains(pdev->request_queue, cancelID2); - urbdrc = (URBDRC_PLUGIN*)pdev->urbdrc; - cancelID = (id1) ? cancelID1 : cancelID2; + if (transfer) + { + URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)pdev->urbdrc; - 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ free(descriptor); } +fail: libusb_free_device_list(libusb_list, 1); *devArray = (IUDEVICE**)array; return num; diff -Nru freerdp2-2.2.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.h freerdp2-2.3.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.h --- freerdp2-2.2.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevice.h 2021-02-25 08:51:41.000000000 +0000 @@ -63,7 +63,7 @@ MSUSB_CONFIG_DESCRIPTOR* MsConfig; LIBUSB_CONFIG_DESCRIPTOR* LibusbConfig; - wHashTable* request_queue; + wArrayList* request_queue; URBDRC_PLUGIN* urbdrc; }; diff -Nru freerdp2-2.2.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevman.c freerdp2-2.3.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevman.c --- freerdp2-2.2.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevman.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/urbdrc/client/libusb/libusb_udevman.c 2021-02-25 08:51:41.000000000 +0000 @@ -399,6 +399,36 @@ 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 @@ 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 */ diff -Nru freerdp2-2.2.0+dfsg1/channels/urbdrc/client/urbdrc_main.c freerdp2-2.3.0+dfsg1/channels/urbdrc/client/urbdrc_main.c --- freerdp2-2.2.0+dfsg1/channels/urbdrc/client/urbdrc_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/urbdrc/client/urbdrc_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -621,6 +621,12 @@ 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 @@ 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 @@ 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; } /** diff -Nru freerdp2-2.2.0+dfsg1/channels/urbdrc/client/urbdrc_main.h freerdp2-2.3.0+dfsg1/channels/urbdrc/client/urbdrc_main.h --- freerdp2-2.2.0+dfsg1/channels/urbdrc/client/urbdrc_main.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/urbdrc/client/urbdrc_main.h 2021-02-25 08:51:41.000000000 +0000 @@ -85,6 +85,7 @@ wLog* log; IWTSListener* listener; + BOOL initialized; }; typedef BOOL (*PREGISTERURBDRCSERVICE)(IWTSPlugin* plugin, IUDEVMAN* udevman); @@ -174,6 +175,7 @@ void (*setAlreadySend)(IUDEVICE* idev); void (*setChannelClosed)(IUDEVICE* idev); + void (*markChannelClosed)(IUDEVICE* idev); char* (*getPath)(IUDEVICE* idev); void (*free)(IUDEVICE* idev); @@ -205,6 +207,7 @@ 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); diff -Nru freerdp2-2.2.0+dfsg1/channels/urbdrc/common/urbdrc_helpers.c freerdp2-2.3.0+dfsg1/channels/urbdrc/common/urbdrc_helpers.c --- freerdp2-2.2.0+dfsg1/channels/urbdrc/common/urbdrc_helpers.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/urbdrc/common/urbdrc_helpers.c 2021-02-25 08:51:41.000000000 +0000 @@ -391,7 +391,7 @@ pos = Stream_GetPosition(s); if (write) { - length = Stream_GetPosition(s); + length = pos; Stream_SetPosition(s, 0); } else @@ -407,7 +407,7 @@ 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) diff -Nru freerdp2-2.2.0+dfsg1/channels/video/client/video_main.c freerdp2-2.3.0+dfsg1/channels/video/client/video_main.c --- freerdp2-2.2.0+dfsg1/channels/video/client/video_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/channels/video/client/video_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -76,6 +76,7 @@ VIDEO_LISTENER_CALLBACK* data_callback; VideoClientContext* context; + BOOL initialized; }; typedef struct _VIDEO_PLUGIN VIDEO_PLUGIN; @@ -1035,6 +1036,11 @@ 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 @@ if (status == CHANNEL_RC_OK) video->dataListener->pInterface = video->wtsPlugin.pInterface; + video->initialized = status == CHANNEL_RC_OK; return status; } diff -Nru freerdp2-2.2.0+dfsg1/ci/cmake-preloads/config-ios.txt freerdp2-2.3.0+dfsg1/ci/cmake-preloads/config-ios.txt --- freerdp2-2.2.0+dfsg1/ci/cmake-preloads/config-ios.txt 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/ci/cmake-preloads/config-ios.txt 2021-02-25 08:51:41.000000000 +0000 @@ -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") diff -Nru freerdp2-2.2.0+dfsg1/ci/cmake-preloads/config-linux-all.txt freerdp2-2.3.0+dfsg1/ci/cmake-preloads/config-linux-all.txt --- freerdp2-2.2.0+dfsg1/ci/cmake-preloads/config-linux-all.txt 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/ci/cmake-preloads/config-linux-all.txt 2021-02-25 08:51:41.000000000 +0000 @@ -7,6 +7,7 @@ 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") diff -Nru freerdp2-2.2.0+dfsg1/client/common/client.c freerdp2-2.3.0+dfsg1/client/common/client.c --- freerdp2-2.2.0+dfsg1/client/common/client.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/common/client.c 2021-02-25 08:51:41.000000000 +0000 @@ -663,6 +663,66 @@ 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_ex(freerdp* instance, BOOL (*window_events)(freerdp* instance)) { + UINT32 error; UINT32 maxRetries; UINT32 numRetries = 0; rdpSettings* settings; @@ -681,11 +742,21 @@ 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) { diff -Nru freerdp2-2.2.0+dfsg1/client/common/cmdline.c freerdp2-2.3.0+dfsg1/client/common/cmdline.c --- freerdp2-2.2.0+dfsg1/client/common/cmdline.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/common/cmdline.c 2021-02-25 08:51:41.000000000 +0000 @@ -1403,14 +1403,14 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ *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 @@ } *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 @@ 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 @@ } 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") { diff -Nru freerdp2-2.2.0+dfsg1/client/common/cmdline.h freerdp2-2.3.0+dfsg1/client/common/cmdline.h --- freerdp2-2.2.0+dfsg1/client/common/cmdline.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/common/cmdline.h 2021-02-25 08:51:41.000000000 +0000 @@ -63,7 +63,7 @@ { "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, "", NULL, NULL, -1, NULL, @@ -102,8 +102,12 @@ "Client Build Number sent to server (influences smartcard behaviour, see [MS-RDPESC])" }, { "client-hostname", COMMAND_LINE_VALUE_REQUIRED, "", 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:]", + BoolValueTrue, NULL, -1, NULL, + "Redirect clipboard. " + " * use-selection: ... (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 @@ "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 =,... pairs to remap scancodes", NULL, NULL, -1, NULL, + "Keyboard scancode remapping" }, { "kbd-subtype", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Keyboard subtype" }, { "kbd-type", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Keyboard type" }, diff -Nru freerdp2-2.2.0+dfsg1/client/common/file.c freerdp2-2.3.0+dfsg1/client/common/file.c --- freerdp2-2.2.0+dfsg1/client/common/file.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/common/file.c 2021-02-25 08:51:41.000000000 +0000 @@ -1772,8 +1772,7 @@ { 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; } diff -Nru freerdp2-2.2.0+dfsg1/client/Sample/tf_freerdp.c freerdp2-2.3.0+dfsg1/client/Sample/tf_freerdp.c --- freerdp2-2.2.0+dfsg1/client/Sample/tf_freerdp.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/Sample/tf_freerdp.c 2021-02-25 08:51:41.000000000 +0000 @@ -338,12 +338,10 @@ 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; } diff -Nru freerdp2-2.2.0+dfsg1/client/Wayland/wlf_cliprdr.c freerdp2-2.3.0+dfsg1/client/Wayland/wlf_cliprdr.c --- freerdp2-2.2.0+dfsg1/client/Wayland/wlf_cliprdr.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/Wayland/wlf_cliprdr.c 2021-02-25 08:51:41.000000000 +0000 @@ -306,7 +306,8 @@ 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); } diff -Nru freerdp2-2.2.0+dfsg1/client/Wayland/wlf_input.c freerdp2-2.3.0+dfsg1/client/Wayland/wlf_input.c --- freerdp2-2.2.0+dfsg1/client/Wayland/wlf_input.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/Wayland/wlf_input.c 2021-02-25 08:51:41.000000000 +0000 @@ -137,9 +137,9 @@ { 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 @@ 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 @@ * positive: 0 ... 0xFF -> slow ... fast * negative: 0 ... 0xFF -> fast ... slow */ - step = abs(direction); - if (step > 0xFF) - step = 0xFF; - - /* Negative rotation, so count down steps from top */ - if (flags & PTR_FLAGS_WHEEL_NEGATIVE) - step = 0xFF - step; - - flags |= step; + 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; + } - return freerdp_input_send_mouse_event(input, flags, (UINT16)x, (UINT16)y); + return TRUE; } BOOL wlf_handle_key(freerdp* instance, const UwacKeyEvent* ev) @@ -208,13 +208,34 @@ 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); } diff -Nru freerdp2-2.2.0+dfsg1/client/Wayland/wlf_input.h freerdp2-2.3.0+dfsg1/client/Wayland/wlf_input.h --- freerdp2-2.2.0+dfsg1/client/Wayland/wlf_input.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/Wayland/wlf_input.h 2021-02-25 08:51:41.000000000 +0000 @@ -36,5 +36,6 @@ 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 */ diff -Nru freerdp2-2.2.0+dfsg1/client/Wayland/wlfreerdp.c freerdp2-2.3.0+dfsg1/client/Wayland/wlfreerdp.c --- freerdp2-2.2.0+dfsg1/client/Wayland/wlfreerdp.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/Wayland/wlfreerdp.c 2021-02-25 08:51:41.000000000 +0000 @@ -270,7 +270,8 @@ 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 @@ 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 @@ 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 @@ break; + case UWAC_EVENT_CLOSE: + context->closed = TRUE; + + break; + default: break; } @@ -482,6 +497,12 @@ 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 @@ 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 @@ 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) diff -Nru freerdp2-2.2.0+dfsg1/client/Wayland/wlfreerdp.h freerdp2-2.3.0+dfsg1/client/Wayland/wlfreerdp.h --- freerdp2-2.2.0+dfsg1/client/Wayland/wlfreerdp.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/Wayland/wlfreerdp.h 2021-02-25 08:51:41.000000000 +0000 @@ -42,6 +42,8 @@ UwacSeat* seat; BOOL fullscreen; + BOOL closed; + BOOL focusing; /* Channels */ RdpeiClientContext* rdpei; diff -Nru freerdp2-2.2.0+dfsg1/client/X11/cli/xfreerdp.c freerdp2-2.3.0+dfsg1/client/X11/cli/xfreerdp.c --- freerdp2-2.2.0+dfsg1/client/X11/cli/xfreerdp.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/cli/xfreerdp.c 2021-02-25 08:51:41.000000000 +0000 @@ -34,6 +34,7 @@ int main(int argc, char* argv[]) { + int rc = 1; int status; HANDLE thread; xfContext* xfc; @@ -56,31 +57,31 @@ 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; } diff -Nru freerdp2-2.2.0+dfsg1/client/X11/generate_argument_docbook.c freerdp2-2.3.0+dfsg1/client/X11/generate_argument_docbook.c --- freerdp2-2.2.0+dfsg1/client/X11/generate_argument_docbook.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/generate_argument_docbook.c 2021-02-25 08:51:41.000000000 +0000 @@ -244,7 +244,8 @@ 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) { diff -Nru freerdp2-2.2.0+dfsg1/client/X11/xf_client.c freerdp2-2.3.0+dfsg1/client/X11/xf_client.c --- freerdp2-2.2.0+dfsg1/client/X11/xf_client.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/xf_client.c 2021-02-25 08:51:41.000000000 +0000 @@ -299,8 +299,8 @@ 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 @@ * another window. This make xf_error_handler() a potential * debugger breakpoint. */ + XUngrabKeyboard(d, CurrentTime); return xf_error_handler(d, ev); } @@ -1075,8 +1076,9 @@ { 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 @@ 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 @@ 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 @@ 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); diff -Nru freerdp2-2.2.0+dfsg1/client/X11/xf_cliprdr.c freerdp2-2.3.0+dfsg1/client/X11/xf_cliprdr.c --- freerdp2-2.2.0+dfsg1/client/X11/xf_cliprdr.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/xf_cliprdr.c 2021-02-25 08:51:41.000000000 +0000 @@ -68,6 +68,9 @@ 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 @@ /* 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 @@ * * @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 @@ Stream_Free(formats, TRUE); } -static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) +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) { - 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.formats = (CLIPRDR_FORMAT*)formats; formatList.msgType = CB_FORMAT_LIST; - clipboard->context->ClientFormatList(clipboard->context, &formatList); + + 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; + formats = xf_cliprdr_get_client_formats(clipboard, &numFormats); + xf_cliprdr_send_format_list(clipboard, formats, numFormats); xf_cliprdr_free_formats(formats, numFormats); } @@ -619,11 +710,12 @@ (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 @@ 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 @@ 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 @@ 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 @@ } 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_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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ int i, n = 0; rdpChannels* channels; xfClipboard* clipboard; + const char* selectionAtom; if (!(clipboard = (xfClipboard*)calloc(1, sizeof(xfClipboard)))) { @@ -1618,14 +1771,19 @@ 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 @@ } ClipboardDestroy(clipboard->system); + xf_clipboard_formats_free(clipboard); free(clipboard->data); free(clipboard->data_raw); free(clipboard->respond); diff -Nru freerdp2-2.2.0+dfsg1/client/X11/xf_disp.c freerdp2-2.3.0+dfsg1/client/X11/xf_disp.c --- freerdp2-2.2.0+dfsg1/client/X11/xf_disp.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/xf_disp.c 2021-02-25 08:51:41.000000000 +0000 @@ -46,7 +46,6 @@ UINT64 lastSentDate; int targetWidth, targetHeight; BOOL activated; - BOOL waitingResize; BOOL fullscreen; UINT16 lastSentDesktopOrientation; UINT32 lastSentDesktopScaleFactor; @@ -113,11 +112,10 @@ 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 @@ } else { - xfDisp->waitingResize = TRUE; layout.Flags = DISPLAY_CONTROL_MONITOR_PRIMARY; layout.Top = layout.Left = 0; layout.Width = xfDisp->targetWidth; @@ -134,8 +131,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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, diff -Nru freerdp2-2.2.0+dfsg1/client/X11/xf_event.c freerdp2-2.3.0+dfsg1/client/X11/xf_event.c --- freerdp2-2.2.0+dfsg1/client/X11/xf_event.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/xf_event.c 2021-02-25 08:51:41.000000000 +0000 @@ -503,6 +503,10 @@ 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 @@ 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 @@ } 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_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; } diff -Nru freerdp2-2.2.0+dfsg1/client/X11/xf_graphics.c freerdp2-2.3.0+dfsg1/client/X11/xf_graphics.c --- freerdp2-2.2.0+dfsg1/client/X11/xf_graphics.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/xf_graphics.c 2021-02-25 08:51:41.000000000 +0000 @@ -226,13 +226,156 @@ 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 @@ 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 @@ { #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 @@ { #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 @@ #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 @@ 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 @@ { #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 @@ 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); diff -Nru freerdp2-2.2.0+dfsg1/client/X11/xf_input.c freerdp2-2.3.0+dfsg1/client/X11/xf_input.c --- freerdp2-2.2.0+dfsg1/client/X11/xf_input.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/xf_input.c 2021-02-25 08:51:41.000000000 +0000 @@ -480,13 +480,19 @@ 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 diff -Nru freerdp2-2.2.0+dfsg1/client/X11/xf_keyboard.c freerdp2-2.3.0+dfsg1/client/X11/xf_keyboard.c --- freerdp2-2.2.0+dfsg1/client/X11/xf_keyboard.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/xf_keyboard.c 2021-02-25 08:51:41.000000000 +0000 @@ -43,8 +43,16 @@ #include #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 @@ { 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 @@ 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 @@ xfc->KeyboardState[keycode] = FALSE; } } + xf_sync_kbd_state(xfc); } BOOL xf_keyboard_key_pressed(xfContext* xfc, KeySym keysym) @@ -216,9 +221,7 @@ 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 @@ 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 @@ 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 @@ // 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 @@ 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 @@ } // ungrabbed - ungrabKeyboardWithRightCtrl = FALSE; + xfc->ungrabKeyboardWithRightCtrl = FALSE; } BOOL xf_keyboard_set_indicators(rdpContext* context, UINT16 led_flags) diff -Nru freerdp2-2.2.0+dfsg1/client/X11/xf_keyboard.h freerdp2-2.3.0+dfsg1/client/X11/xf_keyboard.h --- freerdp2-2.2.0+dfsg1/client/X11/xf_keyboard.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/xf_keyboard.h 2021-02-25 08:51:41.000000000 +0000 @@ -44,7 +44,7 @@ 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); diff -Nru freerdp2-2.2.0+dfsg1/client/X11/xf_rail.c freerdp2-2.3.0+dfsg1/client/X11/xf_rail.c --- freerdp2-2.2.0+dfsg1/client/X11/xf_rail.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/xf_rail.c 2021-02-25 08:51:41.000000000 +0000 @@ -180,7 +180,7 @@ 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 @@ * 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; diff -Nru freerdp2-2.2.0+dfsg1/client/X11/xfreerdp.h freerdp2-2.3.0+dfsg1/client/X11/xfreerdp.h --- freerdp2-2.2.0+dfsg1/client/X11/xfreerdp.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/xfreerdp.h 2021-02-25 08:51:41.000000000 +0000 @@ -28,6 +28,10 @@ typedef struct xf_context xfContext; +#ifdef WITH_XCURSOR +#include +#endif + #include #include "xf_window.h" @@ -48,6 +52,14 @@ #include #include +#if !defined(XcursorUInt) +typedef unsigned int XcursorUInt; +#endif + +#if !defined(XcursorPixel) +typedef XcursorUInt XcursorPixel; +#endif + struct xf_FullscreenMonitors { UINT32 top; @@ -69,6 +81,12 @@ 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 @@ Atom UTF8_STRING; + Atom _XWAYLAND_MAY_GRAB_KEYBOARD; + Atom _NET_WM_ICON; Atom _MOTIF_WM_HINTS; Atom _NET_CURRENT_DESKTOP; @@ -248,6 +268,8 @@ button_map button_map[NUM_BUTTONS_MAPPED]; BYTE savedMaximizedState; UINT32 locked; + BOOL firstPressRightCtrl; + BOOL ungrabKeyboardWithRightCtrl; }; BOOL xf_create_window(xfContext* xfc); diff -Nru freerdp2-2.2.0+dfsg1/client/X11/xf_window.c freerdp2-2.3.0+dfsg1/client/X11/xf_window.c --- freerdp2-2.2.0+dfsg1/client/X11/xf_window.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/client/X11/xf_window.c 2021-02-25 08:51:41.000000000 +0000 @@ -123,11 +123,11 @@ */ 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 @@ } 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 @@ 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 @@ if (!appWindow) return; + if (xfc->appWindow == appWindow) + xfc->appWindow = NULL; + if (appWindow->gc) XFreeGC(xfc->display, appWindow->gc); diff -Nru freerdp2-2.2.0+dfsg1/cmake/ConfigOptions.cmake freerdp2-2.3.0+dfsg1/cmake/ConfigOptions.cmake --- freerdp2-2.2.0+dfsg1/cmake/ConfigOptions.cmake 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/cmake/ConfigOptions.cmake 2021-02-25 08:51:41.000000000 +0000 @@ -98,12 +98,16 @@ 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_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}) diff -Nru freerdp2-2.2.0+dfsg1/cmake/ConfigOptionsiOS.cmake freerdp2-2.3.0+dfsg1/cmake/ConfigOptionsiOS.cmake --- freerdp2-2.2.0+dfsg1/cmake/ConfigOptionsiOS.cmake 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/cmake/ConfigOptionsiOS.cmake 2021-02-25 08:51:41.000000000 +0000 @@ -19,5 +19,5 @@ 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") diff -Nru freerdp2-2.2.0+dfsg1/CMakeLists.txt freerdp2-2.3.0+dfsg1/CMakeLists.txt --- freerdp2-2.2.0+dfsg1/CMakeLists.txt 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/CMakeLists.txt 2021-02-25 08:51:41.000000000 +0000 @@ -81,7 +81,7 @@ 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 @@ 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 @@ 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") diff -Nru freerdp2-2.2.0+dfsg1/debian/changelog freerdp2-2.3.0+dfsg1/debian/changelog --- freerdp2-2.2.0+dfsg1/debian/changelog 2020-08-25 07:17:57.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/debian/changelog 2021-02-25 15:14:52.000000000 +0000 @@ -1,3 +1,29 @@ +freerdp2 (2.3.0+dfsg1-1) unstable; urgency=medium + + [ Fabio Fantoni ] + * debian/control: + + Add missed binary version deps to avoid issue in some cases + like upgrade to -backports. (Closes: #964147) + + [ Mike Gabriel ] + * New upstream release. (Closes: #893733, #903646). + * debian/control: + + Bump to Standards-Version: 4.5.1. No changes needed. + * debian/copyright: + + Update auto-generated copyright.in file. + + Update copyright attributions: + * debian/patches: + + Drop 1001_spelling-fixes.patch. Applied upstream. + + Revert upstream's removal of the connectErrorCode symbol via + 2002_revert-e4b30a5cb6100a8ea4f320b829c9c5712ed4a783.patch. + This re-instates ABI compatibility with FreeRDP 2.2.0. + * debian/*.symbols: + + Update symbols for FreeRDP 2.3.0. + * debian/watch: + + Switch to format version 4. + + -- Mike Gabriel Thu, 25 Feb 2021 16:14:52 +0100 + freerdp2 (2.2.0+dfsg1-1) unstable; urgency=medium * New upstream release. diff -Nru freerdp2-2.2.0+dfsg1/debian/control freerdp2-2.3.0+dfsg1/debian/control --- freerdp2-2.2.0+dfsg1/debian/control 2020-08-25 07:11:53.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/debian/control 2021-02-25 15:14:52.000000000 +0000 @@ -45,7 +45,7 @@ uuid-dev, xmlto, xsltproc, -Standards-Version: 4.5.0 +Standards-Version: 4.5.1 Rules-Requires-Root: no Homepage: https://www.freerdp.com/ Vcs-Browser: https://salsa.debian.org/debian-remote-team/freerdp2 @@ -56,6 +56,7 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, + libfreerdp-client2-2 (= ${binary:Version}), Provides: freerdp, Replaces: @@ -89,6 +90,7 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, + libwinpr2-2 (= ${binary:Version}), Breaks: libfreerdp2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: @@ -110,6 +112,7 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, + libfreerdp2-2 (= ${binary:Version}), Breaks: libfreerdp-client2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: @@ -129,6 +132,7 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, + libfreerdp2-2 (= ${binary:Version}), Breaks: libfreerdp-server2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: @@ -175,6 +179,7 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, + libwinpr2-2 (= ${binary:Version}), Breaks: libwinpr-tools2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: @@ -233,6 +238,7 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, + libwinpr-tools2-2 (= ${binary:Version}), Description: Windows Portable Runtime library command line utilities WinPR is a spin-off project of FreeRDP which aims at providing a portable implementation of important portions of the Windows API. Just like FreeRDP, @@ -253,6 +259,8 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, + libfreerdp-server2-2 (= ${binary:Version}), + libwinpr-tools2-2 (= ${binary:Version}), Breaks: libfreerdp-shadow2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: @@ -272,6 +280,7 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, + libfreerdp-shadow2-2 (= ${binary:Version}), Breaks: libfreerdp-shadow2 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: @@ -288,6 +297,7 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, + libfreerdp-shadow-subsystem2-2 (= ${binary:Version}), Provides: freerdp, Description: FreeRDP x11 shadowing server @@ -305,6 +315,7 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, + libfreerdp2-2 (= ${binary:Version}), Breaks: libuwac0 (<< 2.0.0~git20170725.1.1648deb+dfsg1-1~), Replaces: @@ -334,6 +345,8 @@ Depends: ${misc:Depends}, ${shlibs:Depends}, + libfreerdp-client2-2 (= ${binary:Version}), + libuwac0-0 (= ${binary:Version}), Description: RDP client for Windows Terminal Services (wayland client) FreeRDP is a libre client/server implementation of the Remote Desktop Protocol (RDP). diff -Nru freerdp2-2.2.0+dfsg1/debian/copyright freerdp2-2.3.0+dfsg1/debian/copyright --- freerdp2-2.2.0+dfsg1/debian/copyright 2020-08-25 07:17:57.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/debian/copyright 2021-02-25 14:19:25.000000000 +0000 @@ -13,6 +13,7 @@ resources/FreeRDP_OSX.icns resources/FreeRDP_Logo_Icon.ai scripts/OpenSSL-DownloadAndBuild.command + scripts/android-build-release.conf winpr/libwinpr/crt/utf.* Files: .clang-format @@ -20,6 +21,7 @@ .github/ISSUE_TEMPLATE/bug_report.md .github/ISSUE_TEMPLATE/feature_request.md .github/PULL_REQUEST_TEMPLATE.md + .github/workflows/codeql-analysis.yml .gitignore .travis.yml channels/client/.gitignore @@ -193,6 +195,7 @@ libfreerdp/codec/test/TestFreeRDPCodecXCrush.c libfreerdp/codec/test/TestFreeRDPCodecZGfx.c libfreerdp/codec/test/rfx.bmp + libfreerdp/codec/test/progressive.bmp libfreerdp/codec/test/test01.bmp libfreerdp/codec/yuv.c libfreerdp/common/test/CMakeLists.txt @@ -1195,7 +1198,7 @@ License: Apache-2.0 Files: channels/audin/client/mac/CMakeLists.txt - channels/audin/client/mac/audin_mac.c + channels/audin/client/mac/audin_mac.m channels/printer/client/cups/CMakeLists.txt channels/printer/client/win/CMakeLists.txt channels/rdpsnd/client/fake/CMakeLists.txt @@ -2077,6 +2080,7 @@ Files: channels/parallel/client/parallel_main.c channels/smartcard/client/smartcard_main.h + channels/smartcard/client/smartcard_operations.h Copyright: 2010, Eduardo Fiss Beloni 2010, O.S. Systems Software Ltda. 2011, Eduardo Fiss Beloni @@ -2239,9 +2243,15 @@ 2016, David PHAM-VAN License: Apache-2.0 -Files: libfreerdp/codec/h264.h -Copyright: 2018, Armin Novak +Files: include/freerdp/channels/echo.h + libfreerdp/codec/h264.h + libfreerdp/codec/progressive.h +Copyright: 2017, Armin Novak + 2017, Thincast Technologies GmbH + 2018, Armin Novak 2018, Thincast Technologies GmbH + 2020, Armin Novak + 2020, Thincast Technologies GmbH License: Apache-2.0 Files: channels/printer/client/printer_main.c @@ -2760,11 +2770,6 @@ 2012, Vic Lee License: Apache-2.0 -Files: libfreerdp/codec/progressive.h -Copyright: 2017, Armin Novak - 2017, Thincast Technologies GmbH -License: Apache-2.0 - Files: libfreerdp/codec/rfx_constants.h Copyright: 2011, Vic Lee License: Apache-2.0 diff -Nru freerdp2-2.2.0+dfsg1/debian/copyright.in freerdp2-2.3.0+dfsg1/debian/copyright.in --- freerdp2-2.2.0+dfsg1/debian/copyright.in 2020-06-29 11:57:29.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/debian/copyright.in 2021-02-25 14:19:25.000000000 +0000 @@ -232,6 +232,7 @@ libfreerdp/locale/keyboard_xkbfile.h libfreerdp/locale/liblocale.h libfreerdp/locale/locale.c + libfreerdp/locale/xkb_layout_ids.c libfreerdp/locale/xkb_layout_ids.h libfreerdp/utils/CMakeLists.txt libfreerdp/utils/pcap.c @@ -577,7 +578,7 @@ 2013-2014, Marc-Andre Moreau 2014, Marc-Andre Moreau 2015, Marc-Andre Moreau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: CMakeCPack.cmake @@ -666,9 +667,7 @@ cmake/compat_2.8.11/BasicConfigVersion-AnyNewerVersion.cmake.in cmake/compat_2.8.11/BasicConfigVersion-ExactVersion.cmake.in cmake/compat_2.8.11/BasicConfigVersion-SameMajorVersion.cmake.in - cmake/compat_2.8.11/CMakePackageConfigHelpers.cmake cmake/compat_2.8.2/FindPkgConfig.cmake - cmake/compat_2.8.3/CMakeParseArguments.cmake cmake/compat_2.8.3/FindPackageHandleStandardArgs.cmake cmake/compat_2.8.6/FeatureSummary.cmake cmake/compat_3.7.0/FindICU.cmake @@ -704,7 +703,6 @@ debian/libwinpr2-2.symbols.kfreebsd-amd64 debian/libwinpr2-2.symbols.kfreebsd-i386 debian/libwinpr2-dev.install - debian/patches/1001_spelling-fixes.patch debian/patches/2001-fake-git-revision.patch debian/patches/README debian/patches/series @@ -713,6 +711,7 @@ debian/upstream debian/watch debian/winpr-utils.install + docs/Doxyfile docs/PrintFormatSpecifiers.md docs/README.android docs/README.ios @@ -733,8 +732,11 @@ libfreerdp/codec/test/TestFreeRDPCodecRemoteFX.c libfreerdp/codec/test/TestFreeRDPCodecXCrush.c libfreerdp/codec/test/TestFreeRDPCodecZGfx.c + libfreerdp/codec/test/progressive.bmp libfreerdp/codec/test/test01.bmp libfreerdp/codec/yuv.c + libfreerdp/common/settings_getters.c + libfreerdp/common/settings_str.c libfreerdp/common/test/CMakeLists.txt libfreerdp/common/test/TestCommonAssistance.c libfreerdp/core/test/CMakeLists.txt @@ -778,12 +780,18 @@ scripts/android-build-jpeg.sh scripts/android-build-openh264.sh scripts/android-build-openssl.sh + scripts/android-build-release.conf scripts/android-build.conf scripts/blacklist-memory-sanitizer.txt scripts/create_release_taball.sh + scripts/fetch_language_identifiers.py + scripts/gprof_generate.sh.cmake scripts/specBytesToCode.py scripts/toolchains_path.py + scripts/update-rdpSettings scripts/update-settings-tests + scripts/update-windows-zones.py + scripts/xcode.sh server/FreeRDP-ServerConfig.cmake.in server/Mac/ModuleOptions.cmake server/Mac/server.crt @@ -804,6 +812,7 @@ server/proxy/modules/README.md server/proxy/server.crt server/proxy/server.key + server/proxy/session-capture/generate_video_from_frames.py server/proxy/session-capture/requirements.txt server/shadow/FreeRDP-ShadowConfig.cmake.in server/shadow/freerdp-shadow-cli.1.in @@ -999,6 +1008,10 @@ winpr/libwinpr/thread/test/TestThreadCommandLineToArgv.c winpr/libwinpr/thread/test/TestThreadCreateProcess.c winpr/libwinpr/timezone/ModuleOptions.cmake + winpr/libwinpr/timezone/TimeZones.c + winpr/libwinpr/timezone/TimeZones.h + winpr/libwinpr/timezone/WindowsZones.c + winpr/libwinpr/timezone/WindowsZones.h winpr/libwinpr/utils/ModuleOptions.cmake winpr/libwinpr/utils/test/CMakeLists.txt winpr/libwinpr/utils/test/TestArrayList.c @@ -1122,11 +1135,11 @@ 2019, Thincast Technologies GmbH 2020, Armin Novak 2020, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/audin/client/mac/CMakeLists.txt - channels/audin/client/mac/audin_mac.c + channels/audin/client/mac/audin_mac.m channels/printer/client/cups/CMakeLists.txt channels/printer/client/win/CMakeLists.txt channels/rdpsnd/client/fake/CMakeLists.txt @@ -1190,7 +1203,7 @@ 2019, Thincast Technologies GmbH 2020, Armin Novak 2020, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/audin/client/audin_main.h @@ -1217,6 +1230,7 @@ libfreerdp/codec/nsc_sse2.c libfreerdp/codec/nsc_sse2.h libfreerdp/codec/rfx_bitstream.h + libfreerdp/codec/rfx_constants.h libfreerdp/codec/rfx_decode.h libfreerdp/codec/rfx_differential.h libfreerdp/codec/rfx_dwt.c @@ -1240,7 +1254,7 @@ 2011, Vic Lee 2011-2012, Vic Lee 2012, Vic Lee -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/client/addin.c @@ -1293,7 +1307,7 @@ 2014, Marc-Andre Moreau 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/tsmf/client/gstreamer/CMakeLists.txt @@ -1340,7 +1354,7 @@ winpr/libwinpr/comm/test/TestTimeouts.c Copyright: 2012, Hewlett-Packard Development Company, L.P. 2014, Hewlett-Packard Development Company, L.P. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/disp/disp_common.c @@ -1370,7 +1384,7 @@ server/proxy/pf_rdpsnd.c server/proxy/pf_rdpsnd.h Copyright: 2019, Kobi Mizrachi -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/geometry/CMakeLists.txt @@ -1400,7 +1414,7 @@ 2016, David Fort 2017, David Fort 2018, David Fort -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: server/proxy/CMakeLists.txt @@ -1429,7 +1443,7 @@ Copyright: 2019, Idan Freiberg 2019, Kobi Mizrachi 2019, Mati Shabtay -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/audin/client/alsa/audin_alsa.c @@ -1456,7 +1470,7 @@ 2014, Vic Lee 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/X11/xf_input.c @@ -1478,7 +1492,7 @@ server/Windows/wf_info.h Copyright: 2012, Corey Clayton 2013, Corey Clayton -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpgfx/server/CMakeLists.txt @@ -1496,24 +1510,7 @@ server/shadow/shadow_subsystem_builtin.c Copyright: 2015, Jiang Zihao 2016, Jiang Zihao -License: Apache (v2.0) - FIXME - -Files: docs/Doxyfile - libfreerdp/common/settings_getters.c - libfreerdp/common/settings_str.c - scripts/fetch_language_identifiers.py - scripts/gprof_generate.sh.cmake - scripts/update-rdpSettings - scripts/update-windows-zones.py - scripts/xcode.sh - server/proxy/session-capture/generate_video_from_frames.py - winpr/libwinpr/timezone/TimeZones.c - winpr/libwinpr/timezone/TimeZones.h - winpr/libwinpr/timezone/WindowsZones.c - winpr/libwinpr/timezone/WindowsZones.h -Copyright: NONE -License: GENERATED FILE +License: Apache License 2.0 FIXME Files: channels/urbdrc/client/CMakeLists.txt @@ -1530,7 +1527,7 @@ channels/urbdrc/common/urbdrc_types.h Copyright: 2012, Alfred Liu 2012, Atrust corp. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/X11/CMakeLists.txt @@ -1549,7 +1546,7 @@ 2012, Marc-Andre Moreau 2012-2013, Corey Clayton 2013, Corey Clayton -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: cmake/FindX11.cmake @@ -1566,7 +1563,21 @@ Copyright: 2011, Marc-Andre Moreau 2011, O.S. Systems Software Ltda. 2011, Otavio Salvador -License: Apache (v2.0) +License: Apache License 2.0 + FIXME + +Files: include/freerdp/heartbeat.h + libfreerdp/core/autodetect.c + libfreerdp/core/autodetect.h + libfreerdp/core/heartbeat.c + libfreerdp/core/heartbeat.h + libfreerdp/core/multitransport.c + libfreerdp/core/multitransport.h + winpr/libwinpr/shell/CMakeLists.txt + winpr/libwinpr/shell/shell.c +Copyright: 2014, Dell Software + 2015, Dell Software +License: Apache License 2.0 FIXME Files: channels/rdpdr/client/irp.h @@ -1587,7 +1598,7 @@ 2012, Vic Lee 2012-2013, Marc-Andre Moreau 2013, Marc-Andre Moreau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: uwac/include/uwac/uwac-tools.h @@ -1602,20 +1613,7 @@ Copyright: 2014, David FORT 2014-2015, David FORT 2015, David FORT -License: NTP (legal disclaimer) - FIXME - -Files: libfreerdp/core/autodetect.c - libfreerdp/core/autodetect.h - libfreerdp/core/heartbeat.c - libfreerdp/core/heartbeat.h - libfreerdp/core/multitransport.c - libfreerdp/core/multitransport.h - winpr/libwinpr/shell/CMakeLists.txt - winpr/libwinpr/shell/shell.c -Copyright: 2014, Dell Software - 2015, Dell Software -License: Apache (v2.0) +License: NTP License (legal disclaimer) FIXME Files: libfreerdp/core/rdp.c @@ -1630,7 +1628,7 @@ 2014, DI (FH) Martin Haimberger 2014, Marc-Andre Moreau 2015, DI (FH) Martin Haimberger -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: server/proxy/modules/modules_api.h @@ -1642,7 +1640,7 @@ server/proxy/pf_modules.h Copyright: 2019, Idan Freiberg 2019, Kobi Mizrachi -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/common/cmdline.h @@ -1657,7 +1655,7 @@ 2015, Thincast Technologies GmbH 2018, Bernhard Miklautz 2018, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/include/winpr/comm.h @@ -1670,7 +1668,7 @@ 2011, O.S. Systems Software Ltda. 2014, Hewlett-Packard Development Company, L.P. 2014, Marc-Andre Moreau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/sysinfo/cpufeatures/NOTICE @@ -1681,7 +1679,7 @@ winpr/libwinpr/utils/corkscrew/symbol_table.h Copyright: 2011, The Android Open Source Project 2016, The Android Open Source Project -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/utils/trio/strio.h @@ -1704,7 +1702,7 @@ winpr/libwinpr/log.h Copyright: 2013, Armin Novak 2014, Armin Novak -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpgfx/client/rdpgfx_main.c @@ -1723,7 +1721,7 @@ 2017, Thincast Technologies GmbH 2020, Armin Novak 2020, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/gateway/ntlm.c @@ -1734,7 +1732,7 @@ Copyright: 2012, Dmitrij Jasnov 2012, Fujitsu Technology Solutions GmbH 2012, Marc-Andre Moreau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/utils/ringbuffer.h @@ -1744,7 +1742,7 @@ libfreerdp/utils/test/TestRingBuffer.c Copyright: 2014, Hardening 2014, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/tsmf/client/CMakeLists.txt @@ -1757,7 +1755,7 @@ 2014, Hewlett-Packard Development Company, L.P. 2014, Marc-Andre Moreau 2015, Hewlett-Packard Development Company, L.P. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/X11/xf_gdi.c @@ -1772,7 +1770,7 @@ 2013, Thincast Technologies GmbH 2014, Norbert Federa 2014, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/utils/profiler.h @@ -1781,7 +1779,7 @@ libfreerdp/utils/profiler.c libfreerdp/utils/stopwatch.c Copyright: 2011, Stephen Erisman -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/cliprdr/client/cliprdr_format.c @@ -1792,7 +1790,7 @@ 2010-2011, Vic Lee 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpdr/client/devman.h @@ -1803,7 +1801,16 @@ 2010-2012, Marc-Andre Moreau 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 + FIXME + +Files: include/freerdp/session.h + uwac/CMakeLists.txt + uwac/include/CMakeLists.txt + uwac/libuwac/CMakeLists.txt +Copyright: 2015, David FORT + 2016, David FORT +License: Apache License 2.0 FIXME Files: include/freerdp/codec/bitmap.h @@ -1813,7 +1820,7 @@ Copyright: 2004-2012, Jay Sorg 2011, Jay Sorg 2012, Jay Sorg -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rail/server/CMakeLists.txt @@ -1821,7 +1828,7 @@ channels/rail/server/rail_main.h include/freerdp/server/rail.h Copyright: 2019, Mati Shabtay -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/audin/client/oss/CMakeLists.txt @@ -1829,7 +1836,7 @@ channels/tsmf/client/oss/CMakeLists.txt channels/tsmf/client/oss/tsmf_oss.c Copyright: 2015, Rozhuk Ivan -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/utils/passphrase.h @@ -1837,7 +1844,7 @@ libfreerdp/utils/passphrase.c libfreerdp/utils/signal.c Copyright: 2011, Shea Levy -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/audin/client/opensles/opensl_io.c @@ -1845,7 +1852,19 @@ channels/rdpsnd/client/opensles/opensl_io.c channels/rdpsnd/client/opensles/opensl_io.h Copyright: 2012, Victor Lazzarini -License: BSD (3 clause) +License: BSD 3-clause "New" or "Revised" License + FIXME + +Files: include/freerdp/channels/echo.h + libfreerdp/codec/h264.h + libfreerdp/codec/progressive.h +Copyright: 2017, Armin Novak + 2017, Thincast Technologies GmbH + 2018, Armin Novak + 2018, Thincast Technologies GmbH + 2020, Armin Novak + 2020, Thincast Technologies GmbH +License: Apache License 2.0 FIXME Files: include/freerdp/codec/rfx.h @@ -1855,7 +1874,7 @@ 2012, Vic Lee 2016, Armin Novak 2016, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpdr/server/rdpdr_main.c @@ -1865,7 +1884,19 @@ 2014, Dell Software 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 + FIXME + +Files: channels/parallel/client/parallel_main.c + channels/smartcard/client/smartcard_main.h + channels/smartcard/client/smartcard_operations.h +Copyright: 2010, Eduardo Fiss Beloni + 2010, O.S. Systems Software Ltda. + 2011, Eduardo Fiss Beloni + 2011, O.S. Systems Software Ltda. + 2015, DI (FH) Martin Haimberger + 2015, Thincast Technologies GmbH +License: Apache License 2.0 FIXME Files: channels/tsmf/client/tsmf_ifman.c @@ -1875,7 +1906,7 @@ 2012, Hewlett-Packard Development Company, L.P. 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rail/client/rail_main.h @@ -1886,15 +1917,7 @@ 2011, Vic Lee 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) - FIXME - -Files: include/freerdp/session.h - uwac/CMakeLists.txt - uwac/include/CMakeLists.txt -Copyright: 2015, David FORT - 2016, David FORT -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/utils/wlog/JournaldAppender.c @@ -1902,7 +1925,7 @@ winpr/libwinpr/utils/wlog/UdpAppender.c Copyright: 2015, David FORT 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/Wayland/CMakeLists.txt @@ -1910,7 +1933,7 @@ client/Wayland/wlf_input.h Copyright: 2014, Manuel Bachmann 2015, David Fort -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/include/winpr/file.h @@ -1918,7 +1941,7 @@ winpr/libwinpr/path/shell.c Copyright: 2012, Marc-Andre Moreau 2016, David PHAM-VAN -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/tsmf/client/tsmf_codec.c @@ -1926,7 +1949,7 @@ channels/tsmf/client/tsmf_decoder.h Copyright: 2010-2011, Vic Lee 2012, Hewlett-Packard Development Company, L.P. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/security.c @@ -1937,7 +1960,7 @@ 2013, Norbert Federa 2014, Norbert Federa 2016, Norbert Federa -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/rail.h @@ -1945,7 +1968,7 @@ libfreerdp/core/window.h Copyright: 2011, Marc-Andre Moreau 2011, Roman Barabanov -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/include/winpr/ssl.h @@ -1955,14 +1978,14 @@ 2014, Thincast Technologies GmbH 2015, Norbert Federa 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: LICENSE client/X11/xf_floatbar.c client/X11/xf_floatbar.h Copyright: NONE -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/utils/wlog/JournaldAppender.h @@ -1970,7 +1993,7 @@ winpr/libwinpr/utils/wlog/UdpAppender.h Copyright: 2015, David FORT 2015, Thincast Technologies GmbH -License: NTP (legal disclaimer) +License: NTP License (legal disclaimer) FIXME Files: winpr/libwinpr/utils/trio/triodef.h @@ -1984,7 +2007,7 @@ winpr/libwinpr/sspi/Kerberos/kerberos.h Copyright: 2015, ANSSI, Author Thomas Calderon 2017, Dorian Ducournau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/sspi/sspi_gss.c @@ -1992,13 +2015,13 @@ Copyright: 2015, ANSSI, Author Thomas Calderon 2015, Marc-Andre Moreau 2017, Dorian Ducournau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/clipboard/posix.c winpr/libwinpr/clipboard/posix.h Copyright: 2017, Alexei Lozovsky -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/audin/client/opensles/audin_opensl_es.c @@ -2006,7 +2029,7 @@ Copyright: 2013, Armin Novak 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/printer/client/cups/printer_cups.c @@ -2015,13 +2038,13 @@ 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH 2016, Armin Novak -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/utils/wlog/CallbackAppender.c winpr/libwinpr/utils/wlog/CallbackAppender.h Copyright: 2014, Armin Novak -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/primitives/prim_YUV_neon.c @@ -2030,7 +2053,7 @@ 2016-2017, Armin Novak 2016-2017, Norbert Federa 2016-2017, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/codec/nsc.h @@ -2039,21 +2062,21 @@ 2012, Vic Lee 2016, Armin Novak 2016, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/sshagent/CMakeLists.txt channels/sshagent/client/CMakeLists.txt Copyright: 2012, Marc-Andre Moreau 2017, Ben Cohen -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/proxy.c libfreerdp/core/proxy.h Copyright: 2014, Christian Plattner 2016, Christian Plattner -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/include/winpr/wtsapi.h @@ -2061,7 +2084,7 @@ Copyright: 2013, Marc-Andre Moreau 2015, Copyright 2015 Thincast Technologies GmbH 2015, DI (FH) Martin Haimberger -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpsnd/client/ios/CMakeLists.txt @@ -2069,13 +2092,13 @@ Copyright: 2012, Laxmikant Rashinkar 2012, Marc-Andre Moreau 2013, Corey Clayton -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/handle/nonehandle.c winpr/libwinpr/handle/nonehandle.h Copyright: 2014, DI (FH) Martin Haimberger -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpei/server/rdpei_main.c @@ -2084,18 +2107,7 @@ 2014, Thincast Technologies Gmbh. 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) - FIXME - -Files: channels/parallel/client/parallel_main.c - channels/smartcard/client/smartcard_main.h -Copyright: 2010, Eduardo Fiss Beloni - 2010, O.S. Systems Software Ltda. - 2011, Eduardo Fiss Beloni - 2011, O.S. Systems Software Ltda. - 2015, DI (FH) Martin Haimberger - 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/freerdp.h @@ -2103,7 +2115,7 @@ Copyright: 2009-2011, Jay Sorg 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/cliprdr/cliprdr_common.c @@ -2112,7 +2124,7 @@ 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH 2019, Kobi Mizrachi -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/audin/client/oss/audin_oss.c @@ -2120,21 +2132,21 @@ Copyright: 2015, DI (FH) Martin Haimberger 2015, Rozhuk Ivan 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpei/rdpei_common.c channels/rdpei/rdpei_common.h Copyright: 2013, Marc-Andre Moreau 2014, David Fort -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/primitives/prim_YUV_opencl.c libfreerdp/primitives/primitives.cl Copyright: 2019, David Fort 2019, Rangee Gmbh -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpdr/client/CMakeLists.txt @@ -2143,13 +2155,13 @@ 2014, Marc-Andre Moreau 2016, David PHAM-VAN 2016, Inuvika Inc. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/gateway/rdg.c libfreerdp/core/gateway/rdg.h Copyright: 2015, Denis Vincent -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/sspi/Negotiate/negotiate.c @@ -2157,7 +2169,7 @@ Copyright: 2011-2014, Marc-Andre Moreau 2012-2014, Marc-Andre Moreau 2017, Dorian Ducournau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/serial/client/serial_main.c @@ -2165,7 +2177,7 @@ Copyright: 2011, Eduardo Fiss Beloni 2011, O.S. Systems Software Ltda. 2014, Hewlett-Packard Development Company, L.P. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/primitives/prim_colors.c @@ -2174,97 +2186,98 @@ 2011, Norbert Federa 2011, Stephen Erisman 2012, Hewlett-Packard Development Company, L.P. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/api.h libfreerdp/core/settings.c Copyright: 2009-2011, Jay Sorg -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/tools/CMakeLists.txt winpr/tools/makecert-cli/CMakeLists.txt Copyright: 2012, Marc-Andre Moreau 2016, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/codec/rfx_neon.c libfreerdp/codec/rfx_neon.h Copyright: 2011, Martin Fleisz -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/codec/h264.h libfreerdp/codec/h264_mf.c Copyright: 2014, Mike McDonald -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/crypto/opensslcompat.c libfreerdp/crypto/opensslcompat.h Copyright: 2016, Norbert Federa -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/codec/rfx_decode.c libfreerdp/codec/rfx_encode.c Copyright: 2011, Norbert Federa 2011, Vic Lee -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/include/winpr/strlst.h winpr/libwinpr/utils/strlst.c Copyright: 2018, Pascal Bourguignon -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/crypto/der.h libfreerdp/crypto/der.c Copyright: 2011, Samsung, Author Jiten Pathy -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c winpr/libwinpr/sysinfo/cpufeatures/cpu-features.h Copyright: 2010, The Android Open Source Project -License: BSD (2 clause) +License: BSD 2-clause "Simplified" License FIXME Files: cmake/GetGitRevisionDescription.cmake cmake/GetGitRevisionDescription.cmake.in Copyright: Iowa State University 2009-2010. -License: BSL (v1.0) +License: Boost Software License 1.0 FIXME -Files: libfreerdp/codec/test/rfx.bmp - resources/FreeRDP-fav.ico -Copyright: +Files: cmake/compat_2.8.11/CMakePackageConfigHelpers.cmake + cmake/compat_2.8.3/CMakeParseArguments.cmake +Copyright: 2010, Alexander Neundorf + 2012, Alexander Neundorf License: UNKNOWN FIXME Files: channels/rdpsnd/client/ios/TPCircularBuffer.c channels/rdpsnd/client/ios/TPCircularBuffer.h Copyright: 2012-2013, A Tasty Pixel -License: zlib/libpng +License: zlib/libpng license FIXME Files: winpr/libwinpr/utils/lodepng/lodepng.c winpr/libwinpr/utils/lodepng/lodepng.h Copyright: 2005-2014, Lode Vandevenne -License: zlib/libpng +License: zlib/libpng license FIXME Files: cmake/FindXRandR.cmake Copyright: 2012, Alam Arias -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: resources/conv_to_ewm_prop.py Copyright: 2011, Anthony Tong -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/smartcard/client/smartcard_operations.c @@ -2275,7 +2288,7 @@ 2017, Armin Novak 2017, Thincast Technologies GmbH Alexi Volkov 2006 -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/smartcard/client/smartcard_main.c @@ -2285,13 +2298,7 @@ 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH 2016, David PHAM-VAN -License: Apache (v2.0) - FIXME - -Files: libfreerdp/codec/h264.h -Copyright: 2018, Armin Novak - 2018, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/printer/client/printer_main.c @@ -2300,7 +2307,7 @@ 2015, Thincast Technologies GmbH 2016, Armin Novak 2016, David PHAM-VAN -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/printer/client/win/printer_win.c @@ -2308,7 +2315,7 @@ 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH 2016, Armin Novak -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpdr/client/devman.c @@ -2317,34 +2324,34 @@ 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH 2016, Armin Novak -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/settings.h Copyright: 2009-2011, Jay Sorg 2010-2012, Marc-Andre Moreau 2016, Armin Novak -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/common/settings.c Copyright: 2012, Marc-Andre Moreau 2016, Armin Novak -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/common/cmdline.c Copyright: 2012, Marc-Andre Moreau 2014, Norbert Federa 2016, Armin Novak -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/codec/h264_openh264.c Copyright: 2014, Armin Novak 2014, Mike McDonald 2015, Vic Lee -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/X11/xf_client.c @@ -2354,7 +2361,7 @@ 2014, Thincast Technologies GmbH 2016, Armin Novak 2016, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/drive/client/drive_file.c @@ -2367,7 +2374,7 @@ 2016, Inuvika Inc. 2017, Armin Novak 2017, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpdr/client/rdpdr_main.c @@ -2377,7 +2384,7 @@ 2015-2016, Thincast Technologies GmbH 2016, Armin Novak 2016, David PHAM-VAN -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rail/client/rail_orders.c @@ -2387,7 +2394,7 @@ 2015, Thincast Technologies GmbH 2017, Armin Novak 2017, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rail/client/rail_main.c @@ -2398,7 +2405,7 @@ 2015, Thincast Technologies GmbH 2017, Armin Novak 2017, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpdr/client/rdpdr_capabilities.c @@ -2407,7 +2414,7 @@ 2015, DI (FH) Martin Haimberger 2015-2016, Thincast Technologies GmbH 2016, Armin Novak -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/audin/client/audin_main.c @@ -2415,14 +2422,14 @@ 2015, Armin Novak 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/file/file.h Copyright: 2015, Armin Novak 2015, Thincast Technologies GmbH 2016, David PHAM-VAN -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/X11/xf_window.c @@ -2430,14 +2437,14 @@ 2012, HP Development Company, LLC 2016, Armin Novak 2016, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/tsmf/client/gstreamer/tsmf_gstreamer.c Copyright: 2012, HP Development Company, LLC 2014, Armin Novak 2014, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/codec/region.c @@ -2445,21 +2452,21 @@ 2014, Thincast Technologies GmbH 2017, Armin Novak 2017, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/codec/include/bitmap.c Copyright: 2011, Jay Sorg 2016, Armin Novak 2016, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/Wayland/wlfreerdp.c Copyright: 2014, Manuel Bachmann 2016, Armin Novak 2016, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/primitives/prim_YUV.c @@ -2468,7 +2475,7 @@ 2015-2017, Norbert Federa 2015-2017, Thincast Technologies GmbH 2015-2017, Vic Lee -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/include/winpr/stream.h @@ -2476,7 +2483,7 @@ 2012, Marc-Andre Moreau 2017, Armin Novak 2017, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/fastpath.c @@ -2484,35 +2491,35 @@ 2014, Norbert Federa 2017, Armin Novak 2017, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/graphics.h Copyright: 2016, Armin Novak 2016, Thinast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/path/shell_ios.m Copyright: 2016, Armin Novak 2016, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdp2tcp/client/rdp2tcp_main.c Copyright: 2017, Artur Zaprzala -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/client/sshagent.h Copyright: 2017, Ben Cohen -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/sshagent/client/sshagent_main.h Copyright: 2013, Christian Hofstaedtler 2017, Ben Cohen -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/sshagent/client/sshagent_main.c @@ -2520,56 +2527,56 @@ 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH 2017, Ben Cohen -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: cmake/CheckCmakeCompat.cmake Copyright: 2012, Bernhard Miklautz -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/file/file.c Copyright: 2015, Bernhard Miklautz 2015, Thincast Technologies GmbH 2016, David PHAM-VAN -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/sysinfo/sysinfo.c Copyright: 2012, Marc-Andre Moreau 2013, Bernhard Miklautz -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/include/winpr/wlog.h Copyright: 2013, Marc-Andre Moreau 2015, Bernhard Miklautz 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/echo/client/echo_main.h Copyright: 2013, Christian Hofstaedtler -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/echo/client/echo_main.c Copyright: 2013, Christian Hofstaedtler 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/server.h Copyright: 2014, Marc-Andre Moreau 2015, Copyright 2015 Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/channels.c Copyright: 2011, Vic Lee 2015, Copyright 2015 Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: cmake/FindXi.cmake @@ -2577,14 +2584,14 @@ 2011, O.S. Systems Software Ltda. 2011, Otavio Salvador 2013, Corey Clayton -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpei/server/rdpei_main.h Copyright: 2014, David Fort 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/drive/client/drive_file.h @@ -2595,7 +2602,7 @@ 2015, Thincast Technologies GmbH 2016, David PHAM-VAN 2016, Inuvika Inc. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpsnd/client/mac/rdpsnd_mac.m @@ -2604,7 +2611,7 @@ 2015, Thincast Technologies GmbH 2016, David PHAM-VAN 2016, Inuvika Inc. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpdr/client/rdpdr_main.h @@ -2614,7 +2621,7 @@ 2015, Thincast Technologies GmbH 2016, David PHAM-VAN 2016, Inuvika Inc. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpsnd/client/rdpsnd_main.c @@ -2624,7 +2631,7 @@ 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH 2016, David PHAM-VAN -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpsnd/client/winmm/rdpsnd_winmm.c @@ -2633,7 +2640,7 @@ 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH 2016, David PHAM-VAN -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/disp/client/disp_main.c @@ -2641,7 +2648,7 @@ 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH 2016, David PHAM-VAN -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/drive/client/drive_main.c @@ -2650,14 +2657,14 @@ 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH 2016, David PHAM-VAN -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpsnd/client/ios/rdpsnd_ios.c Copyright: 2013, Dell Software 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/gateway/tsg.c @@ -2665,7 +2672,7 @@ 2012, Fujitsu Technology Solutions GmbH 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/nla.c @@ -2674,14 +2681,14 @@ 2015, Thincast Technologies GmbH 2016, Martin Fleisz 2017, Dorian Ducournau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/cliprdr/client/cliprdr_main.h Copyright: 2009-2011, Jay Sorg 2010-2011, Vic Lee 2015, DI (FH) Martin Haimberger -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/certificate.c @@ -2689,14 +2696,14 @@ 2011, Marc-Andre Moreau 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/gcc.c Copyright: 2011, Marc-Andre Moreau 2014, DI (FH) Martin Haimberger 2014, Norbert Federa -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/nego.c @@ -2704,7 +2711,7 @@ 2014, Norbert Federa 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rail/client/rail_orders.h @@ -2712,85 +2719,85 @@ 2011, Roman Barabanov 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/audin/client/winmm/audin_winmm.c Copyright: 2013, Zhang Zhaolong 2015, DI (FH) Martin Haimberger 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/peer.c Copyright: 2011, Vic Lee 2014, DI (FH) Martin Haimberger -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/channels/rdpei.h Copyright: 2013, Marc-Andre Moreau 2014, David FORT 2014, Thincast Technologies Gmbh. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: channels/rdpei/server/CMakeLists.txt Copyright: 2014, David FORT 2014, Thincast Technologies Gmbh. -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/primitives/primitives.c Copyright: 2011, Martin Fleisz 2012, Hewlett-Packard Development Company, L.P. 2019, David Fort -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/X11/xf_monitor.c Copyright: 2011, Marc-Andre Moreau 2017, David Fort 2018, Kai Harms -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/core/license.c Copyright: 2011-2013, Marc-Andre Moreau 2014, Norbert Federa 2018, David Fort -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/codec/h264.c Copyright: 2014, Mike McDonald 2017, David Fort -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/include/winpr/shell.h Copyright: 2015, Dell Software 2016, David PHAM-VAN -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/file/generic.c Copyright: 2012, Marc-Andre Moreau 2014, Hewlett-Packard Development Company, L.P. 2016, David PHAM-VAN -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/autodetect.h Copyright: 2014, Dell Software 2014, Vic Lee -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/X11/cli/xfreerdp.c Copyright: 2011, Marc-Andre Moreau 2012, HP Development Company, LLC -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: CMakeLists.txt @@ -2798,13 +2805,13 @@ 2011, O.S. Systems Software Ltda. 2011, Otavio Salvador 2012, HP Development Company, LLC -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/synch/wait.c Copyright: 2012, Marc-Andre Moreau 2014, Hardening -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/file/namedPipeClient.c @@ -2812,161 +2819,135 @@ 2014, Hewlett-Packard Development Company, L.P. 2015, Thincast Technologies GmbH 2015, bernhard.miklautz@thincast.com -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/types.h Copyright: 2009-2011, Jay Sorg 2011, Marc-Andre Moreau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: include/freerdp/channels/channels.h Copyright: 2009-2011, Jay Sorg 2010-2011, Vic Lee -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: winpr/libwinpr/sspi/Negotiate/negotiate.h Copyright: 2011-2012, Jiten Pathy -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/crypto/certificate.c Copyright: 2011, Jiten Pathy 2011-2012, Marc-Andre Moreau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: client/Wayland/wlfreerdp.h Copyright: 2014, Manuel Bachmann -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: server/Sample/sfreerdp.c Copyright: 2011, Marc-Andre Moreau 2011, Vic Lee 2014, Norbert Federa -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/codec/h264_x264.c Copyright: 2015, Marc-André Moreau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/codec/h264_ffmpeg.c Copyright: 2014, Mike McDonald 2014, erbth 2015, Marc-André Moreau -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: cmake/ConfigOptionsiOS.cmake Copyright: 2013, Martin Fleisz 2013, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: cmake/FindXmlto.cmake Copyright: 2011, Nils Andresen -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/codec/rfx_sse2.c Copyright: 2011, Norbert Federa 2011, Stephen Erisman -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/codec/rfx.c Copyright: 2011, Vic Lee 2015, Norbert Federa 2015, Thincast Technologies GmbH -License: Apache (v2.0) +License: Apache License 2.0 FIXME Files: libfreerdp/codec/nsc_types.h Copyright: 2011, Samsung, Author Jiten Pathy 2012, Vic Lee -License: Apache (v2.0) - FIXME - -Files: libfreerdp/codec/progressive.h -Copyright: 2017, Armin Novak - 2017, Thincast Technologies GmbH -License: Apache (v2.0) CC0 - FIXME - -Files: libfreerdp/codec/rfx_constants.h -Copyright: 2011, Vic Lee -License: Apache (v2.0) CC0 - FIXME - -Files: uwac/libuwac/CMakeLists.txt -Copyright: 2015, David FORT -License: Apache (v2.0) GENERATED FILE - FIXME - -Files: libfreerdp/locale/xkb_layout_ids.c -Copyright: 2009-2012, Marc-Andre Moreau -License: Apache (v2.0) GENERATED FILE +License: Apache License 2.0 FIXME Files: cmake/FindGStreamer_1_0.cmake Copyright: 2012, Raphael Kubo da Costa -License: BSD (2 clause) +License: BSD 2-clause "Simplified" License FIXME Files: cmake/Findlibusb-1.0.cmake Copyright: 2006, Andreas Schneider 2008, Kyle Machulis -License: BSD (3 clause) - FIXME - -Files: debian/changelog -Copyright: rules,watch}: -License: GENERATED FILE +License: BSD 3-clause "New" or "Revised" License FIXME -Files: winpr/libwinpr/crt/casing.c -Copyright: was claimed by the wine -License: GENERATED FILE +Files: debian/.copyright.swp +Copyright: utf-8 +License: GNU Lesser General Public License FIXME Files: uwac/protocols/server-decoration.xml Copyright: 2015, Martin Gräßlin -License: LGPL (v2.1 or later) +License: GNU Lesser General Public License v2.1 or later FIXME Files: uwac/libuwac/uwac-clipboard.c Copyright: 2018, Armin Novak 2018, Thincast Technologies GmbH -License: NTP (legal disclaimer) +License: NTP License (legal disclaimer) FIXME Files: uwac/libuwac/uwac-os.c Copyright: 2012, Collabora, Ltd. -License: NTP (legal disclaimer) +License: NTP License (legal disclaimer) FIXME Files: uwac/libuwac/uwac-os.h Copyright: 2012, Collabora, Ltd. 2014, David FORT -License: NTP (legal disclaimer) +License: NTP License (legal disclaimer) FIXME Files: uwac/libuwac/uwac-utils.c Copyright: 2008, Kristian Høgsberg 2012, Collabora, Ltd. 2014, David FORT -License: NTP (legal disclaimer) +License: NTP License (legal disclaimer) FIXME Files: include/freerdp/codec/region.h Copyright: 2014, Hardening 2014, Thincast Technologies GmbH -License: NTP (legal disclaimer) +License: NTP License (legal disclaimer) FIXME Files: cmake/WindowsDLLVersion.rc.in @@ -3071,9 +3052,17 @@ License: UNKNOWN FIXME +Files: debian/changelog +Copyright: attributions. +License: UNKNOWN + FIXME + Files: resources/FreeRDP_Install.bmp Copyright: bνrÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mʺoº§a•AbGQ4Q4Z> ”QÌ»pijdîéÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïëߟ‰C¢ŒH£J£J£J£J£J£J£J£J£J£J£J£J£J£J¤ŽK†DO1R5S6R5O1°œW˺oijdïêÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøöñ£ŒI¡‹H£J£J£J£J£J£J£J£J£J£J£J£J£J£J¥L”}=M0R5S6Q3X; + •VÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿĶŒœ + •çäÝõóðÝØÏ + IJdǶlÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mǶlʹoͽrͽrͽrͽrͽqʹoǶlÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mνr‘z=A"G)D%÷ööÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúøòȸpǵkÈ·lÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·mÈ·m̼q License: UNKNOWN FIXME @@ -3085,6 +3074,17 @@ License: UNKNOWN FIXME +Files: winpr/libwinpr/crt/casing.c +Copyright: was claimed by the wine +License: UNKNOWN + FIXME + +Files: resources/FreeRDP-fav.ico +Copyright: •RÿÈ·mÿÈ·mÿÈ·mÿÀ®fÿÁ³€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚϞÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿÈ·mÿ¶¤ + —eÿêçáÿêçáÿ +License: UNKNOWN + FIXME + Files: resources/FreeRDP.ico Copyright: šƒªœ„¦¡Œ´¬™¸¬˜º¯œº·žÀ±„´‰Æ¹‘˾™Å¼¬ÏÀ‚ЄÓŋÔǏÎßÕȒØ͚ÜÑ£ÝÓ¦ßÖ¬ÌĶÈʶÎƹÐÈ»àÖ®à×°áØ°âÙ´ÛÕËÜÖÌáÛÓèäÞëçâëèãìéäòðìæóóìûýûúùüüûýýý/P"p0>°MÏ[ðiÿyÿŠ1ÿQÿ¯qÿÁ‘ÿÒ±ÿåÑÿÿÿ/Pp ° ÏÂðÑÿØÿ1ÞÿQãÿqéÿ‘ïÿ±öÿÑÿÿÿ/&PAp[t°ŽÏ©ðÃÿÒÿØ1ÿÝQÿäqÿê‘ÿð±ÿöÑÿÿÿ/P"p0>°MÏ[ðiÿyÿŠ1ÿQÿ¯qÿÁ‘ÿÒ±ÿåÑÿÿÿ/Pp ° @@ -3093,6 +3093,15 @@ Files: winpr/libwinpr/utils/test/lodepng_32bit.bmp Copyright: «î15í&+ì!%ì %ì$ì#ì#ì#ì#ì#ì#ì#ì#ì#ì#ì$ì$ì$ì$ì %ì!%ì!%ì"'í#(í%*í(,í(,íí+0í/3í.2î15î16î38î49î6:î7;î7;î8<î8<î8<î8<î8<î8<î8<î8<î8=î8=ï;?ï;?ï@DïAFðIMðJNñSWñUYñ`ñ + í½¤èºŸæ¸˜áµ’Þ²ŒÛ±‡×®‚Ô®|Ï­wÌ­uɬrÇ­pÄ®qîp°s³uµx·z¼€Ã¿ƒÃŊÄɏÄϕÅԚÄÛ + ó¤®ó©´ó±·ó´¼ò½¿ò¿ÁîÆ¿ìÅÁêɽæÈ»äɶÜɳØÉ­ÐʬÍ˦ÅÌ¢¿Î9ä.0ã%,â!+â+â,â -â"/ã$3ã'3ã(:ä0:ä0@å6?å4Cå9?å5Bå8>å3?å5<ä1=å2:ä0<ä19ä/<ä1<ä1=å2=å2?å5@å6Bå8Då:Fæ<Hæ>KæANçDOçERçHRçHTèKTèKXèOYèP_éWaéYfê^lëdrìkxíqîx„î}‰ï‚ï‡ðŠ’폒폏ꏎ琍呌ᒋà“*â&á&á%á%á%á&á&á&á(â(â)â,â +â,â ,â ,â ,â ,â *â*â)â*â)â*â)â+â*â+â+â,â!,â!.ã#/ã$0ã%2ã&3ã'3ã(3ã(5ã*5ã*7ä,8ä-;ä0;ä0Bå8Aå7Iæ?Iæ?SèJRçI[éRXèO_éW_éVcêZ_éWbêY_éWaéY_éV`èY_çWaèZ%á$á$á#á$á#á$á$á$á$á$á$á%á%á%á%á%á%á%á%á%á$á%á$á%á$á%á%á%á%á%á&á&á&á&á&á&á'â'â'â(â'â(â)â+â,â ,â!/ã$/ã$4ã)3ã(9ä.8ä-;ä0:ä0=å2;ä0=å2:ä0<ä19ä/;ä09ä/<ä1$á#á#á#á#á#á#á#á#á#á#á#á$á$á#á$á#á$á#á$á#á$á#á#á#á$á#á$á#á$á#á$á#á$á$á$á$á$á$á$á$á$á$á$á%á%á%á&á&á&á'â(â)â)â)â+â*â*â)â*â)â*â)â*â%á$á$á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á$á#á$á#á$á$á$á$á$á$á%á$á%á%á%á%á%á$á%á$á%á*â&á%á$á$á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á$á#á#á#á5ã*,â!(â&á%á$á$á$á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á$á#á$á#á$á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#áMçD=å23ã(-â"*â(â&á&á%á%á%á$á$á$á$á$á$á$á%á$á%á$á%á$á%á$á%á%á%á$á%á$á$á$á$á$á$á$á#á$á#á$á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#á#árìk_éWPçFDå:<ä14ã)2ã&.ã#,â!+â*â)â(â(â'â(â(â'â)â)â)â)â*â)â*â)â*â*â*â)â)â(â(â'â'â&á&á&á&á&á%á%á%á%á$á$á$á$á$á#á$á#á#á#á#á#á#á#á$á#á$á#á#á#ážò™ŠïƒyírjëbaéYVèMPçFHæ>Fæ;>å3?å49ä.9ä/5ã*9ä.5ã*9ä.8ä-9ä/9ä/;ä09ä/;ä09ä/;ä0;ä0;ä0<ä1;ä0:ä09ä.9ä.5ã*4ã)3ã'1ã&/ã$.ã#-â"-â",â ,â *â*â(â'â'â&á&á%á%á%á%á%á%á%á%á%á%á%á$á%á$á%á +License: UNKNOWN + FIXME + +Files: libfreerdp/codec/test/rfx.bmp +Copyright: ïübºú™Üû¹ôÿ²ìû«æ÷£åÿѱdðŸéŸ&ò™QðãXïÕdãÀeá½eຠ+ òߔðÔ{ôÇbøºXï°Næ¦Hâ£:ט8͊5Ä{!¸p„œ;ô“ + øƒÀ÷®×÷mÃÿ„ÚÿŒäû”î÷žíø§ìú´ñùÁöøÈöüÐöÿÓòþºôüèþÿêý÷ãýýÜüÿñ License: UNKNOWN FIXME diff -Nru freerdp2-2.2.0+dfsg1/debian/libfreerdp2-2.symbols freerdp2-2.3.0+dfsg1/debian/libfreerdp2-2.symbols --- freerdp2-2.2.0+dfsg1/debian/libfreerdp2-2.symbols 2020-08-25 07:17:57.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/debian/libfreerdp2-2.symbols 2021-02-25 15:06:25.000000000 +0000 @@ -291,6 +291,7 @@ freerdp_keyboard_get_rdp_scancode_from_x11_keycode@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_keyboard_get_x11_keycode_from_rdp_scancode@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_keyboard_init@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + freerdp_keyboard_init_ex@Base 2.3.0+dfsg1 freerdp_keyboard_layouts_free@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_listener_free@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_listener_new@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 @@ -310,6 +311,7 @@ freerdp_peer_new@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_performance_flags_make@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_performance_flags_split@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + freerdp_planar_switch_bgr@Base 2.3.0+dfsg1 freerdp_reconnect@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_register_addin_provider@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_send_error_info@Base 2.1.0+dfsg1 @@ -527,11 +529,13 @@ profiler_print_footer@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 profiler_print_header@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 progressive_compress@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + progressive_compress_ex@Base 2.3.0+dfsg1 progressive_context_free@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 progressive_context_new@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 progressive_context_reset@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 progressive_create_surface_context@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 progressive_decompress@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + progressive_decompress_ex@Base 2.3.0+dfsg1 progressive_delete_surface_context@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 rail_read_unicode_string@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 rectangle_is_empty@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 @@ -557,6 +561,7 @@ rfx_context_set_pixel_format@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 rfx_encode_message@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 rfx_encode_messages@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + rfx_encode_messages_ex@Base 2.3.0+dfsg1 rfx_message_free@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 rfx_message_get_rect_count@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 rfx_message_get_tile_count@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 diff -Nru freerdp2-2.2.0+dfsg1/debian/libfreerdp-client2-2.symbols freerdp2-2.3.0+dfsg1/debian/libfreerdp-client2-2.symbols --- freerdp2-2.2.0+dfsg1/debian/libfreerdp-client2-2.symbols 2020-06-29 11:51:50.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/debian/libfreerdp-client2-2.symbols 2021-02-25 15:06:10.000000000 +0000 @@ -5,12 +5,14 @@ client_auto_reconnect_ex@Base 2.0.0~git20181120.1.e21b72c95+dfsg1 client_cli_authenticate@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 client_cli_gw_authenticate@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + client_cli_present_gateway_message@Base 2.3.0+dfsg1 client_cli_verify_certificate@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 client_cli_verify_certificate_ex@Base 2.0.0~git20190204.1.2693389a+dfsg1 client_cli_verify_changed_certificate@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 client_cli_verify_changed_certificate_ex@Base 2.0.0~git20190204.1.2693389a+dfsg1 cliprdr_parse_file_list@Base 2.0.0~git20170725.1.1648deb+dfsg1 cliprdr_serialize_file_list@Base 2.0.0~git20170725.1.1648deb+dfsg1 + cliprdr_serialize_file_list_ex@Base 2.3.0+dfsg1 del_device@Base 2.1.0+dfsg1 freerdp_channels_addin_list_free@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 freerdp_channels_client_find_static_entry@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 diff -Nru freerdp2-2.2.0+dfsg1/debian/libfreerdp-server2-2.symbols freerdp2-2.3.0+dfsg1/debian/libfreerdp-server2-2.symbols --- freerdp2-2.2.0+dfsg1/debian/libfreerdp-server2-2.symbols 2020-08-25 07:17:57.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/debian/libfreerdp-server2-2.symbols 2021-02-25 15:06:37.000000000 +0000 @@ -26,6 +26,7 @@ rdpei_server_init@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 rdpei_server_resume@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 rdpei_server_send_sc_ready@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 + rdpei_server_send_sc_ready_ex@Base 2.3.0+dfsg1 rdpei_server_suspend@Base 2.0.0~git20160317.1.75ae3f5+dfsg1 rdpgfx_server_context_free@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 rdpgfx_server_context_new@Base 2.0.0~git20161130.1.e60d0d5+dfsg1 diff -Nru freerdp2-2.2.0+dfsg1/debian/patches/1001_spelling-fixes.patch freerdp2-2.3.0+dfsg1/debian/patches/1001_spelling-fixes.patch --- freerdp2-2.2.0+dfsg1/debian/patches/1001_spelling-fixes.patch 2020-06-29 11:51:50.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/debian/patches/1001_spelling-fixes.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -Description: Minor typo fix. -Author: Mike Gabriel - ---- a/client/common/cmdline.h -+++ b/client/common/cmdline.h -@@ -63,7 +63,7 @@ static const COMMAND_LINE_ARGUMENT_A arg - { "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, "", NULL, NULL, -1, NULL, diff -Nru freerdp2-2.2.0+dfsg1/debian/patches/2002_revert-e4b30a5cb6100a8ea4f320b829c9c5712ed4a783.patch freerdp2-2.3.0+dfsg1/debian/patches/2002_revert-e4b30a5cb6100a8ea4f320b829c9c5712ed4a783.patch --- freerdp2-2.2.0+dfsg1/debian/patches/2002_revert-e4b30a5cb6100a8ea4f320b829c9c5712ed4a783.patch 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/debian/patches/2002_revert-e4b30a5cb6100a8ea4f320b829c9c5712ed4a783.patch 2021-02-25 15:08:00.000000000 +0000 @@ -0,0 +1,166 @@ +Description: This is a revert of upstream commit e4b30a5cb6100a8ea4f320b829c9c5712ed4a783 (breaking ABI compatibility with FreeRDP 2.2.0) +Author: Mike Gabriel + +#diff --git a/client/Mac/cli/AppDelegate.m b/client/Mac/cli/AppDelegate.m +#index b7abcde70..698695676 100644 +#--- a/client/Mac/cli/AppDelegate.m +#+++ b/client/Mac/cli/AppDelegate.m +#@@ -199,7 +199,6 @@ void mac_set_view_size(rdpContext *context, MRDPView *view); +# +# void AppDelegate_ConnectionResultEventHandler(void *ctx, ConnectionResultEventArgs *e) +# { +#- rdpContext *context = (rdpContext *)ctx; +# NSLog(@"ConnectionResult event result:%d\n", e->result); +# +# if (_singleDelegate) +#@@ -207,15 +206,11 @@ void AppDelegate_ConnectionResultEventHandler(void *ctx, ConnectionResultEventAr +# if (e->result != 0) +# { +# NSString *message = nil; +#- DWORD code = freerdp_get_last_error(context); +#- switch (code) +#+ +#+ if (connectErrorCode == AUTHENTICATIONERROR) +# { +#- case FREERDP_ERROR_AUTHENTICATION_FAILED: +#- message = [NSString +#- stringWithFormat:@"%@", @"Authentication failure, check credentials."]; +#- break; +#- default: +#- break; +#+ message = [NSString +#+ stringWithFormat:@"%@", @"Authentication failure, check credentials."]; +# } +# +# // Making sure this should be invoked on the main UI thread. +diff --git a/include/freerdp/error.h b/include/freerdp/error.h +index 0fb51608b..f9d4b6ab0 100644 +--- a/include/freerdp/error.h ++++ b/include/freerdp/error.h +@@ -177,6 +177,30 @@ 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 + */ +diff --git a/libfreerdp/core/errinfo.c b/libfreerdp/core/errinfo.c +index abfe96efd..e635847dc 100644 +--- a/libfreerdp/core/errinfo.c ++++ b/libfreerdp/core/errinfo.c +@@ -34,6 +34,8 @@ + ERRINFO_##_code, "ERRINFO_" #_code, ERRINFO_##_code##_STRING, category \ + } + ++int connectErrorCode; ++ + /* Protocol-independent codes */ + + #define ERRINFO_RPC_INITIATED_DISCONNECT_STRING \ +diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c +index 81183e76d..9094bc346 100644 +--- a/libfreerdp/core/freerdp.c ++++ b/libfreerdp/core/freerdp.c +@@ -55,6 +55,8 @@ + + #define TAG FREERDP_TAG("core") + ++/* connectErrorCode is 'extern' in error.h. See comment there.*/ ++ + UINT freerdp_channel_add_init_handle_data(rdpChannelHandles* handles, void* pInitHandle, + void* pUserData) + { +@@ -161,6 +163,7 @@ BOOL freerdp_connect(freerdp* instance) + + /* We always set the return code to 0 before we start the connect sequence*/ + instance->ConnectionCallbackState = CLIENT_STATE_INITIAL; ++ connectErrorCode = 0; + freerdp_set_last_error_log(instance->context, FREERDP_ERROR_SUCCESS); + clearChannelError(instance->context); + ResetEvent(instance->context->abortEvent); +@@ -890,6 +893,61 @@ void freerdp_set_last_error_ex(rdpContext* context, UINT32 lastError, const char + } + + context->LastError = lastError; ++ ++ switch (lastError) ++ { ++ case FREERDP_ERROR_PRE_CONNECT_FAILED: ++ connectErrorCode = PREECONNECTERROR; ++ break; ++ ++ case FREERDP_ERROR_CONNECT_UNDEFINED: ++ connectErrorCode = UNDEFINEDCONNECTERROR; ++ break; ++ ++ case FREERDP_ERROR_POST_CONNECT_FAILED: ++ connectErrorCode = POSTCONNECTERROR; ++ break; ++ ++ case FREERDP_ERROR_DNS_ERROR: ++ connectErrorCode = DNSERROR; ++ break; ++ ++ case FREERDP_ERROR_DNS_NAME_NOT_FOUND: ++ connectErrorCode = DNSNAMENOTFOUND; ++ break; ++ ++ case FREERDP_ERROR_CONNECT_FAILED: ++ connectErrorCode = CONNECTERROR; ++ break; ++ ++ case FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR: ++ connectErrorCode = MCSCONNECTINITIALERROR; ++ break; ++ ++ case FREERDP_ERROR_TLS_CONNECT_FAILED: ++ connectErrorCode = TLSCONNECTERROR; ++ break; ++ ++ case FREERDP_ERROR_AUTHENTICATION_FAILED: ++ connectErrorCode = AUTHENTICATIONERROR; ++ break; ++ ++ case FREERDP_ERROR_INSUFFICIENT_PRIVILEGES: ++ connectErrorCode = INSUFFICIENTPRIVILEGESERROR; ++ break; ++ ++ case FREERDP_ERROR_CONNECT_CANCELLED: ++ connectErrorCode = CANCELEDBYUSER; ++ break; ++ ++ case FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED: ++ connectErrorCode = CONNECTERROR; ++ break; ++ ++ case FREERDP_ERROR_CONNECT_TRANSPORT_FAILED: ++ connectErrorCode = CONNECTERROR; ++ break; ++ } + } + + const char* freerdp_get_logon_error_info_type(UINT32 type) diff -Nru freerdp2-2.2.0+dfsg1/debian/patches/series freerdp2-2.3.0+dfsg1/debian/patches/series --- freerdp2-2.2.0+dfsg1/debian/patches/series 2020-08-25 07:17:57.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/debian/patches/series 2021-02-25 15:07:13.000000000 +0000 @@ -1,2 +1,2 @@ -1001_spelling-fixes.patch 2001-fake-git-revision.patch +2002_revert-e4b30a5cb6100a8ea4f320b829c9c5712ed4a783.patch diff -Nru freerdp2-2.2.0+dfsg1/debian/watch freerdp2-2.3.0+dfsg1/debian/watch --- freerdp2-2.2.0+dfsg1/debian/watch 2020-06-29 11:51:50.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/debian/watch 2021-02-25 15:14:52.000000000 +0000 @@ -1,4 +1,4 @@ -version=3 +version=4 opts=\ filenamemangle=s/.*\/v?([\d\.-]+)\.tar\.gz/freerdp-$1.tar.gz/,\ dversionmangle=s/\+dfsg1//,\ diff -Nru freerdp2-2.2.0+dfsg1/.github/workflows/codeql-analysis.yml freerdp2-2.3.0+dfsg1/.github/workflows/codeql-analysis.yml --- freerdp2-2.2.0+dfsg1/.github/workflows/codeql-analysis.yml 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/.github/workflows/codeql-analysis.yml 2021-02-25 08:51:41.000000000 +0000 @@ -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 diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/altsec.h freerdp2-2.3.0+dfsg1/include/freerdp/altsec.h --- freerdp2-2.2.0+dfsg1/include/freerdp/altsec.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/altsec.h 2021-02-25 08:51:41.000000000 +0000 @@ -187,6 +187,7 @@ 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 @@ 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 */ diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/channels/audin.h freerdp2-2.3.0+dfsg1/include/freerdp/channels/audin.h --- freerdp2-2.2.0+dfsg1/include/freerdp/channels/audin.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/channels/audin.h 2021-02-25 08:51:41.000000000 +0000 @@ -24,4 +24,6 @@ #include #include +#define AUDIN_DVC_CHANNEL_NAME "AUDIO_INPUT" + #endif /* FREERDP_CHANNEL_AUDIN_H */ diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/channels/cliprdr.h freerdp2-2.3.0+dfsg1/include/freerdp/channels/cliprdr.h --- freerdp2-2.2.0+dfsg1/include/freerdp/channels/cliprdr.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/channels/cliprdr.h 2021-02-25 08:51:41.000000000 +0000 @@ -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 @@ #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 } diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/channels/echo.h freerdp2-2.3.0+dfsg1/include/freerdp/channels/echo.h --- freerdp2-2.2.0+dfsg1/include/freerdp/channels/echo.h 1970-01-01 00:00:00.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/channels/echo.h 2021-02-25 08:51:41.000000000 +0000 @@ -0,0 +1,30 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Audio Input Redirection Virtual Channel + * + * Copyright 2020 Armin Novak + * 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 +#include +#include + +#define ECHO_DVC_CHANNEL_NAME "ECHO" + +#endif /* FREERDP_CHANNEL_ECHO_H */ diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/channels/rdpei.h freerdp2-2.3.0+dfsg1/include/freerdp/channels/rdpei.h --- freerdp2-2.2.0+dfsg1/include/freerdp/channels/rdpei.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/channels/rdpei.h 2021-02-25 08:51:41.000000000 +0000 @@ -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 @@ }; 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 */ diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/client/rdpei.h freerdp2-2.3.0+dfsg1/include/freerdp/client/rdpei.h --- freerdp2-2.2.0+dfsg1/include/freerdp/client/rdpei.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/client/rdpei.h 2021-02-25 08:51:41.000000000 +0000 @@ -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 @@ pcRdpeiSuspendTouch SuspendTouch; pcRdpeiResumeTouch ResumeTouch; + + pcRdpeiGetFeatures GetFeatures; + pcRdpeiAddPen AddPen; + + pcRdpeiPen PenBegin; + pcRdpeiPen PenUpdate; + pcRdpeiPen PenEnd; }; #endif /* FREERDP_CHANNEL_RDPEI_CLIENT_RDPEI_H */ diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/client.h freerdp2-2.3.0+dfsg1/include/freerdp/client.h --- freerdp2-2.2.0+dfsg1/include/freerdp/client.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/client.h 2021-02-25 08:51:41.000000000 +0000 @@ -123,6 +123,12 @@ 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)); diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/codec/color.h freerdp2-2.3.0+dfsg1/include/freerdp/codec/color.h --- freerdp2-2.2.0+dfsg1/include/freerdp/codec/color.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/codec/color.h 2021-02-25 08:51:41.000000000 +0000 @@ -809,6 +809,27 @@ 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 diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/codec/planar.h freerdp2-2.3.0+dfsg1/include/freerdp/codec/planar.h --- freerdp2-2.2.0+dfsg1/include/freerdp/codec/planar.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/codec/planar.h 2021-02-25 08:51:41.000000000 +0000 @@ -97,6 +97,8 @@ BYTE* pTempData; UINT32 nTempStep; + + BOOL bgr; }; #ifdef __cplusplus @@ -116,6 +118,8 @@ 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, diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/codec/progressive.h freerdp2-2.3.0+dfsg1/include/freerdp/codec/progressive.h --- freerdp2-2.2.0+dfsg1/include/freerdp/codec/progressive.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/codec/progressive.h 2021-02-25 08:51:41.000000000 +0000 @@ -37,13 +37,26 @@ { #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, diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/codec/rfx.h freerdp2-2.3.0+dfsg1/include/freerdp/codec/rfx.h --- freerdp2-2.2.0+dfsg1/include/freerdp/codec/rfx.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/codec/rfx.h 2021-02-25 08:51:41.000000000 +0000 @@ -183,16 +183,23 @@ 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); diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/error.h freerdp2-2.3.0+dfsg1/include/freerdp/error.h --- freerdp2-2.2.0+dfsg1/include/freerdp/error.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/error.h 2021-02-25 08:51:41.000000000 +0000 @@ -178,30 +178,6 @@ 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 */ diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/event.h freerdp2-2.3.0+dfsg1/include/freerdp/event.h --- freerdp2-2.2.0+dfsg1/include/freerdp/event.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/event.h 2021-02-25 08:51:41.000000000 +0000 @@ -71,6 +71,11 @@ 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) diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/freerdp.h freerdp2-2.3.0+dfsg1/include/freerdp/freerdp.h --- freerdp2-2.2.0+dfsg1/include/freerdp/freerdp.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/freerdp.h 2021-02-25 08:51:41.000000000 +0000 @@ -70,6 +70,10 @@ #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 @@ 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); diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/gdi/gdi.h freerdp2-2.3.0+dfsg1/include/freerdp/gdi/gdi.h --- freerdp2-2.2.0+dfsg1/include/freerdp/gdi/gdi.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/gdi/gdi.h 2021-02-25 08:51:41.000000000 +0000 @@ -525,6 +525,7 @@ GeometryClientContext* geometry; wLog* log; + UINT32 frameId; }; #ifdef __cplusplus diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/locale/keyboard.h freerdp2-2.3.0+dfsg1/include/freerdp/locale/keyboard.h --- freerdp2-2.2.0+dfsg1/include/freerdp/locale/keyboard.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/locale/keyboard.h 2021-02-25 08:51:41.000000000 +0000 @@ -220,6 +220,8 @@ #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); diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/primary.h freerdp2-2.3.0+dfsg1/include/freerdp/primary.h --- freerdp2-2.2.0+dfsg1/include/freerdp/primary.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/primary.h 2021-02-25 08:51:41.000000000 +0000 @@ -462,6 +462,8 @@ 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 @@ 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 */ diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/secondary.h freerdp2-2.3.0+dfsg1/include/freerdp/secondary.h --- freerdp2-2.2.0+dfsg1/include/freerdp/secondary.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/secondary.h 2021-02-25 08:51:41.000000000 +0000 @@ -172,6 +172,8 @@ 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 @@ 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 */ diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/server/cliprdr.h freerdp2-2.3.0+dfsg1/include/freerdp/server/cliprdr.h --- freerdp2-2.2.0+dfsg1/include/freerdp/server/cliprdr.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/server/cliprdr.h 2021-02-25 08:51:41.000000000 +0000 @@ -126,6 +126,7 @@ rdpContext* rdpcontext; BOOL autoInitializationSequence; UINT32 lastRequestedFormatId; + BOOL hasHugeFileSupport; }; #ifdef __cplusplus diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/server/rdpei.h freerdp2-2.3.0+dfsg1/include/freerdp/server/rdpei.h --- freerdp2-2.2.0+dfsg1/include/freerdp/server/rdpei.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/server/rdpei.h 2021-02-25 08:51:41.000000000 +0000 @@ -41,10 +41,12 @@ /** 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 @@ 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); diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/settings.h freerdp2-2.3.0+dfsg1/include/freerdp/settings.h --- freerdp2-2.2.0+dfsg1/include/freerdp/settings.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/settings.h 2021-02-25 08:51:41.000000000 +0000 @@ -120,7 +120,8 @@ #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 @@ #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 @@ #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 @@ 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 @@ /* 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 @@ default value - currently UNUSED! */ ALIGN64 char* ActionScript; ALIGN64 DWORD Floatbar; + ALIGN64 char* XSelectionAtom; }; typedef struct rdp_settings rdpSettings; diff -Nru freerdp2-2.2.0+dfsg1/include/freerdp/utils/pcap.h freerdp2-2.3.0+dfsg1/include/freerdp/utils/pcap.h --- freerdp2-2.2.0+dfsg1/include/freerdp/utils/pcap.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/include/freerdp/utils/pcap.h 2021-02-25 08:51:41.000000000 +0000 @@ -49,7 +49,11 @@ struct _pcap_record { pcap_record_header header; - void* data; + union + { + void* data; + const void* cdata; + }; UINT32 length; pcap_record* next; }; @@ -76,7 +80,7 @@ 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); diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/color.c freerdp2-2.3.0+dfsg1/libfreerdp/codec/color.c --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/color.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/color.c 2021-02-25 08:51:41.000000000 +0000 @@ -241,6 +241,10 @@ 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 @@ 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 @@ 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)) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/planar.c freerdp2-2.3.0+dfsg1/libfreerdp/codec/planar.c --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/planar.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/planar.c 2021-02-25 08:51:41.000000000 +0000 @@ -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 @@ 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; - } + case PIXEL_FORMAT_BGRA32: + for (x = 0; x < width; x++) + { + *(*ppRgba)++ = *(*ppB)++; + *(*ppRgba)++ = *(*ppG)++; + *(*ppRgba)++ = *(*ppR)++; + *(*ppRgba)++ = *(*ppA)++; + } - return TRUE; + return TRUE; - default: - if (ppA) - { + case PIXEL_FORMAT_BGRX32: 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)++ = 0xFF; } - } - else - { - const BYTE alpha = 0xFF; - for (x = 0; x < width; x++) + return TRUE; + + default: + if (ppA) { - UINT32 color = FreeRDPGetColor(DstFormat, *(*ppR)++, *(*ppG)++, *(*ppB)++, alpha); - WriteColor(*ppRgba, DstFormat, color); - *ppRgba += GetBytesPerPixel(DstFormat); + 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; - return TRUE; + 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 @@ { size_t pos = 0; UINT32 y; + WINPR_UNUSED(planeLength); + if (!plane || !deltaPlane) return FALSE; @@ -548,6 +615,8 @@ 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 @@ { 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 @@ 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 @@ if (!context) return FALSE; + context->bgr = FALSE; context->maxWidth = width; context->maxHeight = height; context->maxPlaneSize = context->maxWidth * context->maxHeight; @@ -1464,3 +1538,8 @@ free(context->rlePlanesBuffer); free(context); } + +void freerdp_planar_switch_bgr(BITMAP_PLANAR_CONTEXT* planar, BOOL bgr) +{ + planar->bgr = bgr; +} diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/progressive.c freerdp2-2.3.0+dfsg1/libfreerdp/codec/progressive.c --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/progressive.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/progressive.c 2021-02-25 08:51:41.000000000 +0000 @@ -396,6 +396,7 @@ } free(surface->tiles); + free(surface->updatedTileIndices); free(surface); } @@ -449,8 +450,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } - return (int)end - start; + return (int)(end - start); } static INLINE INT32 progressive_wb_sync(PROGRESSIVE_CONTEXT* progressive, wStream* s, @@ -2138,8 +2156,17 @@ 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 @@ return -1001; } + if (surface->frameId != frameId) + { + surface->frameId = frameId; + surface->numUpdatedTiles = 0; + } + Stream_StaticInit(&ss, sconv.bp, SrcSize); s = &ss; @@ -2264,12 +2297,12 @@ 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 @@ 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 @@ 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 @@ 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) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/progressive.h freerdp2-2.3.0+dfsg1/libfreerdp/codec/progressive.h --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/progressive.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/progressive.h 2021-02-25 08:51:41.000000000 +0000 @@ -200,6 +200,9 @@ 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 @@ wHashTable* SurfaceContexts; wLog* log; + wStream* buffer; + wStream* rects; + RFX_CONTEXT* rfx_context; }; #endif /* INTERNAL_CODEC_PROGRESSIVE_H */ diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/rfx.c freerdp2-2.3.0+dfsg1/libfreerdp/codec/rfx.c --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/rfx.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/rfx.c 2021-02-25 08:51:41.000000000 +0000 @@ -220,9 +220,6 @@ 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 @@ 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_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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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; +} diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/rfx_decode.c freerdp2-2.3.0+dfsg1/libfreerdp/codec/rfx_decode.c --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/rfx_decode.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/rfx_decode.c 2021-02-25 08:51:41.000000000 +0000 @@ -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 @@ /* 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; diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/rfx_decode.h freerdp2-2.3.0+dfsg1/libfreerdp/codec/rfx_decode.h --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/rfx_decode.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/rfx_decode.h 2021-02-25 08:51:41.000000000 +0000 @@ -24,7 +24,8 @@ #include /* 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 */ diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/rfx_dwt.c freerdp2-2.3.0+dfsg1/libfreerdp/codec/rfx_dwt.c --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/rfx_dwt.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/rfx_dwt.c 2021-02-25 08:51:41.000000000 +0000 @@ -27,7 +27,7 @@ #include "rfx_dwt.h" -void rfx_dwt_2d_decode_block(INT16* buffer, INT16* idwt, int subband_width) +static void rfx_dwt_2d_decode_block(INT16* buffer, INT16* idwt, int subband_width) { INT16 *dst, *l, *h; INT16 *l_dst, *h_dst; diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/rfx_dwt.h freerdp2-2.3.0+dfsg1/libfreerdp/codec/rfx_dwt.h --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/rfx_dwt.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/rfx_dwt.h 2021-02-25 08:51:41.000000000 +0000 @@ -23,7 +23,6 @@ #include #include -FREERDP_LOCAL void rfx_dwt_2d_decode_block(INT16* buffer, INT16* idwt, int subband_width); FREERDP_LOCAL void rfx_dwt_2d_decode(INT16* buffer, INT16* dwt_buffer); FREERDP_LOCAL void rfx_dwt_2d_encode(INT16* buffer, INT16* dwt_buffer); diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/test/CMakeLists.txt freerdp2-2.3.0+dfsg1/libfreerdp/codec/test/CMakeLists.txt --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/test/CMakeLists.txt 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/test/CMakeLists.txt 2021-02-25 08:51:41.000000000 +0000 @@ -20,6 +20,8 @@ ${${MODULE_PREFIX}_DRIVER} ${${MODULE_PREFIX}_TESTS}) +add_definitions(-DCMAKE_CURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") +add_definitions(-DCMAKE_CURRENT_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}") add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) target_link_libraries(${MODULE_NAME} freerdp winpr) Binary files /tmp/tmpq1kBmc/KvX90pXOw5/freerdp2-2.2.0+dfsg1/libfreerdp/codec/test/progressive.bmp and /tmp/tmpq1kBmc/bLWbKtRIHN/freerdp2-2.3.0+dfsg1/libfreerdp/codec/test/progressive.bmp differ diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/test/TestFreeRDPCodecInterleaved.c freerdp2-2.3.0+dfsg1/libfreerdp/codec/test/TestFreeRDPCodecInterleaved.c --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/test/TestFreeRDPCodecInterleaved.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/test/TestFreeRDPCodecInterleaved.c 2021-02-25 08:51:41.000000000 +0000 @@ -36,9 +36,9 @@ const size_t SrcSize = step * h; const float maxDiff = 4.0f * ((bpp < 24) ? 2.0f : 1.0f); UINT32 DstSize = SrcSize; - BYTE* pSrcData = malloc(SrcSize); - BYTE* pDstData = malloc(SrcSize); - BYTE* tmp = malloc(SrcSize); + BYTE* pSrcData = calloc(1, SrcSize); + BYTE* pDstData = calloc(1, SrcSize); + BYTE* tmp = calloc(1, SrcSize); if (!pSrcData || !pDstData || !tmp) goto fail; diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c freerdp2-2.3.0+dfsg1/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c --- freerdp2-2.2.0+dfsg1/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c 2021-02-25 08:51:41.000000000 +0000 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -267,7 +268,7 @@ return 1; } -static BYTE* test_progressive_load_file(char* path, char* file, size_t* size) +static BYTE* test_progressive_load_file(const char* path, const char* file, size_t* size) { FILE* fp; BYTE* buffer; @@ -838,8 +839,9 @@ for (pass = 0; pass < count; pass++) { - status = progressive_decompress(progressive, files[pass].buffer, files[pass].size, - g_DstData, PIXEL_FORMAT_XRGB32, g_DstStep, 0, 0, NULL, 0); + status = + progressive_decompress_ex(progressive, files[pass].buffer, files[pass].size, g_DstData, + PIXEL_FORMAT_XRGB32, g_DstStep, 0, 0, NULL, 0, 0); printf("ProgressiveDecompress: status: %d pass: %d\n", status, pass + 1); region = &(progressive->region); @@ -1017,30 +1019,141 @@ return 0; } +static BOOL diff(BYTE a, BYTE b) +{ + BYTE big = MAX(a, b); + BYTE little = MIN(a, b); + if (big - little <= 0x25) + return TRUE; + return FALSE; +} + +static BOOL colordiff(UINT32 format, UINT32 a, UINT32 b) +{ + BYTE ar, ag, ab, aa; + BYTE br, bg, bb, ba; + SplitColor(a, format, &ar, &ag, &ab, &aa, NULL); + SplitColor(b, format, &br, &bg, &bb, &ba, NULL); + if (!diff(aa, ba) || !diff(ar, br) || !diff(ag, bg) || !diff(ab, bb)) + return FALSE; + return TRUE; +} + +static BOOL test_encode_decode(const char* path) +{ + int x, y; + BOOL res = FALSE; + int rc; + BYTE* resultData = NULL; + BYTE* dstData = NULL; + UINT32 dstSize = 0; + UINT32 ColorFormat = PIXEL_FORMAT_BGRX32; + REGION16 invalidRegion = { 0 }; + wImage* image = winpr_image_new(); + wImage* dstImage = winpr_image_new(); + char* name = GetCombinedPath(path, "progressive.bmp"); + PROGRESSIVE_CONTEXT* progressiveEnc = progressive_context_new(TRUE); + PROGRESSIVE_CONTEXT* progressiveDec = progressive_context_new(FALSE); + + region16_init(&invalidRegion); + if (!image || !dstImage || !name || !progressiveEnc || !progressiveDec) + goto fail; + + rc = winpr_image_read(image, name); + if (rc <= 0) + goto fail; + + resultData = calloc(image->scanline, image->height); + if (!resultData) + goto fail; + + // Progressive encode + rc = progressive_compress_ex(progressiveEnc, image->data, image->scanline * image->height, + ColorFormat, image->width, image->height, image->scanline, NULL, + &dstData, &dstSize); + + // Progressive decode + rc = progressive_create_surface_context(progressiveDec, 0, image->width, image->height); + if (rc <= 0) + goto fail; + + rc = progressive_decompress_ex(progressiveDec, dstData, dstSize, resultData, ColorFormat, + image->scanline, 0, 0, &invalidRegion, 0, 0); + if (rc < 0) + goto fail; + + // Compare result + if (0) // Dump result image for manual inspection + { + *dstImage = *image; + dstImage->data = resultData; + winpr_image_write(dstImage, "/tmp/test.bmp"); + } + for (y = 0; y < image->height; y++) + { + const BYTE* orig = &image->data[y * image->scanline]; + const BYTE* dec = &resultData[y * image->scanline]; + for (x = 0; x < image->width; x++) + { + const BYTE* po = &orig[x * 4]; + const BYTE* pd = &dec[x * 4]; + + const DWORD a = ReadColor(po, ColorFormat); + const DWORD b = ReadColor(pd, ColorFormat); + if (!colordiff(ColorFormat, a, b)) + { + printf("xxxxxxx [%u:%u] %08X != %08X\n", x, y, a, b); + goto fail; + } + } + } + res = TRUE; +fail: + region16_uninit(&invalidRegion); + progressive_context_free(progressiveEnc); + progressive_context_free(progressiveDec); + winpr_image_free(image, TRUE); + winpr_image_free(dstImage, FALSE); + free(resultData); + free(name); + return res; +} + int TestFreeRDPCodecProgressive(int argc, char* argv[]) { + int rc = -1; char* ms_sample_path; char name[8192]; SYSTEMTIME systemTime; WINPR_UNUSED(argc); WINPR_UNUSED(argv); + GetSystemTime(&systemTime); sprintf_s(name, sizeof(name), "EGFX_PROGRESSIVE_MS_SAMPLE-%04" PRIu16 "%02" PRIu16 "%02" PRIu16 "%02" PRIu16 "%02" PRIu16 "%02" PRIu16 "%04" PRIu16, systemTime.wYear, systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds); - ms_sample_path = GetKnownSubPath(KNOWN_PATH_TEMP, name); + ms_sample_path = _strdup(CMAKE_CURRENT_SOURCE_DIR); if (!ms_sample_path) { printf("Memory allocation failed\n"); - return -1; + goto fail; } if (PathFileExistsA(ms_sample_path)) - return test_progressive_ms_sample(ms_sample_path); + { + /* + if (test_progressive_ms_sample(ms_sample_path) < 0) + goto fail; + */ + if (!test_encode_decode(ms_sample_path)) + goto fail; + rc = 0; + } +fail: free(ms_sample_path); - return 0; + return rc; } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/common/assistance.c freerdp2-2.3.0+dfsg1/libfreerdp/common/assistance.c --- freerdp2-2.2.0+dfsg1/libfreerdp/common/assistance.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/common/assistance.c 2021-02-25 08:51:41.000000000 +0000 @@ -790,6 +790,10 @@ char* r; int status; size_t length; + + free(file->password); + file->password = _strdup(password); + p = strstr(buffer, "UPLOADINFO"); if (p) @@ -1172,9 +1176,7 @@ } free(file->filename); - free(file->password); file->filename = _strdup(name); - file->password = _strdup(password); fp = fopen(name, "r"); if (!fp) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/common/settings_getters.c freerdp2-2.3.0+dfsg1/libfreerdp/common/settings_getters.c --- freerdp2-2.2.0+dfsg1/libfreerdp/common/settings_getters.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/common/settings_getters.c 2021-02-25 08:51:41.000000000 +0000 @@ -2247,6 +2247,9 @@ case FreeRDP_KerberosRealm: return settings->KerberosRealm; + case FreeRDP_KeyboardRemappingList: + return settings->KeyboardRemappingList; + case FreeRDP_NtlmSamFile: return settings->NtlmSamFile; @@ -2551,6 +2554,12 @@ settings->KerberosRealm = (val ? _strdup(val) : NULL); return (!val || settings->KerberosRealm != NULL); + case FreeRDP_KeyboardRemappingList: + if (cleanup) + free(settings->KeyboardRemappingList); + settings->KeyboardRemappingList = (val ? _strdup(val) : NULL); + return (!val || settings->KeyboardRemappingList != NULL); + case FreeRDP_NtlmSamFile: if (cleanup) free(settings->NtlmSamFile); diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/common/settings_str.c freerdp2-2.3.0+dfsg1/libfreerdp/common/settings_str.c --- freerdp2-2.2.0+dfsg1/libfreerdp/common/settings_str.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/common/settings_str.c 2021-02-25 08:51:41.000000000 +0000 @@ -324,6 +324,7 @@ { FreeRDP_ImeFileName, 7, "FreeRDP_ImeFileName" }, { FreeRDP_KerberosKdc, 7, "FreeRDP_KerberosKdc" }, { FreeRDP_KerberosRealm, 7, "FreeRDP_KerberosRealm" }, + { FreeRDP_KeyboardRemappingList, 7, "FreeRDP_KeyboardRemappingList" }, { FreeRDP_NtlmSamFile, 7, "FreeRDP_NtlmSamFile" }, { FreeRDP_Password, 7, "FreeRDP_Password" }, { FreeRDP_PasswordHash, 7, "FreeRDP_PasswordHash" }, diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/activation.c freerdp2-2.3.0+dfsg1/libfreerdp/core/activation.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/activation.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/activation.c 2021-02-25 08:51:41.000000000 +0000 @@ -38,14 +38,18 @@ */ static BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s); static BOOL rdp_recv_client_font_list_pdu(wStream* s); +static BOOL rdp_recv_client_persistent_key_list_pdu(wStream* s); static BOOL rdp_recv_server_font_map_pdu(rdpRdp* rdp, wStream* s); static BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s); static BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp); -static void rdp_write_synchronize_pdu(wStream* s, rdpSettings* settings) +static BOOL rdp_write_synchronize_pdu(wStream* s, rdpSettings* settings) { + if (Stream_GetRemainingCapacity(s) < 4) + return FALSE; Stream_Write_UINT16(s, SYNCMSGTYPE_SYNC); /* messageType (2 bytes) */ Stream_Write_UINT16(s, settings->PduSource); /* targetUser (2 bytes) */ + return TRUE; } BOOL rdp_recv_synchronize_pdu(rdpRdp* rdp, wStream* s) @@ -65,7 +69,13 @@ BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp) { wStream* s = rdp_data_pdu_init(rdp); - rdp_write_synchronize_pdu(s, rdp->settings); + if (!s) + return FALSE; + if (!rdp_write_synchronize_pdu(s, rdp->settings)) + { + Stream_Free(s, TRUE); + return FALSE; + } return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId); } @@ -90,7 +100,13 @@ BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp) { wStream* s = rdp_data_pdu_init(rdp); - rdp_write_synchronize_pdu(s, rdp->settings); + if (!s) + return FALSE; + if (!rdp_write_synchronize_pdu(s, rdp->settings)) + { + Stream_Free(s, TRUE); + return FALSE; + } return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId); } @@ -105,11 +121,14 @@ return TRUE; } -static void rdp_write_client_control_pdu(wStream* s, UINT16 action) +static BOOL rdp_write_client_control_pdu(wStream* s, UINT16 action) { + if (Stream_GetRemainingCapacity(s) < 8) + return FALSE; Stream_Write_UINT16(s, action); /* action (2 bytes) */ Stream_Write_UINT16(s, 0); /* grantId (2 bytes) */ Stream_Write_UINT32(s, 0); /* controlId (4 bytes) */ + return TRUE; } BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s) @@ -137,6 +156,13 @@ BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp) { wStream* s = rdp_data_pdu_init(rdp); + if (!s) + return FALSE; + if (Stream_GetRemainingCapacity(s) < 8) + { + Stream_Free(s, TRUE); + return FALSE; + } Stream_Write_UINT16(s, CTRLACTION_COOPERATE); /* action (2 bytes) */ Stream_Write_UINT16(s, 0); /* grantId (2 bytes) */ Stream_Write_UINT32(s, 0); /* controlId (4 bytes) */ @@ -146,6 +172,13 @@ BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp) { wStream* s = rdp_data_pdu_init(rdp); + if (!s) + return FALSE; + if (Stream_GetRemainingCapacity(s) < 8) + { + Stream_Free(s, TRUE); + return FALSE; + } Stream_Write_UINT16(s, CTRLACTION_GRANTED_CONTROL); /* action (2 bytes) */ Stream_Write_UINT16(s, rdp->mcs->userId); /* grantId (2 bytes) */ Stream_Write_UINT32(s, 0x03EA); /* controlId (4 bytes) */ @@ -155,18 +188,29 @@ BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action) { wStream* s = rdp_data_pdu_init(rdp); - rdp_write_client_control_pdu(s, action); + if (!s) + return FALSE; + if (!rdp_write_client_control_pdu(s, action)) + { + Stream_Free(s, TRUE); + return FALSE; + } return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId); } -static void rdp_write_persistent_list_entry(wStream* s, UINT32 key1, UINT32 key2) +static BOOL rdp_write_persistent_list_entry(wStream* s, UINT32 key1, UINT32 key2) { + if (Stream_GetRemainingCapacity(s) < 8) + return FALSE; Stream_Write_UINT32(s, key1); /* key1 (4 bytes) */ Stream_Write_UINT32(s, key2); /* key2 (4 bytes) */ + return TRUE; } -static void rdp_write_client_persistent_key_list_pdu(wStream* s, rdpSettings* settings) +static BOOL rdp_write_client_persistent_key_list_pdu(wStream* s, const rdpSettings* settings) { + if (Stream_GetRemainingCapacity(s) < 24) + return FALSE; Stream_Write_UINT16(s, 0); /* numEntriesCache0 (2 bytes) */ Stream_Write_UINT16(s, 0); /* numEntriesCache1 (2 bytes) */ Stream_Write_UINT16(s, 0); /* numEntriesCache2 (2 bytes) */ @@ -181,38 +225,77 @@ Stream_Write_UINT8(s, 0); /* pad1 (1 byte) */ Stream_Write_UINT16(s, 0); /* pad3 (2 bytes) */ /* entries */ + return TRUE; } BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp) { - wStream* s; - s = rdp_data_pdu_init(rdp); - rdp_write_client_persistent_key_list_pdu(s, rdp->settings); + wStream* s = rdp_data_pdu_init(rdp); + if (!s) + return FALSE; + if (!rdp_write_client_persistent_key_list_pdu(s, rdp->settings)) + { + Stream_Free(s, TRUE); + return FALSE; + } return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->userId); } BOOL rdp_recv_client_font_list_pdu(wStream* s) { - if (Stream_GetRemainingLength(s) < 8) + /* 2.2.1.18 Client Font List PDU */ + return Stream_SafeSeek(s, 8); +} + +BOOL rdp_recv_client_persistent_key_list_pdu(wStream* s) +{ + BYTE flags; + size_t count = 0; + UINT16 cache, x; + /* 2.2.1.17.1 Persistent Key List PDU Data (TS_BITMAPCACHE_PERSISTENT_LIST_PDU) */ + if (Stream_GetRemainingLength(s) < 21) return FALSE; + /* Read numEntriesCacheX for variable length data in PDU */ + for (x = 0; x < 5; x++) + { + Stream_Read_UINT16(s, cache); + count += cache; + } - /* 2.2.1.18.1 Font List PDU Data (TS_FONT_LIST_PDU) */ - Stream_Seek(s, 8); - return TRUE; + /* Skip totalEntriesCacheX */ + if (!Stream_SafeSeek(s, 10)) + return FALSE; + + Stream_Read_UINT8(s, flags); + + /* Skip padding */ + if (!Stream_SafeSeek(s, 3)) + return FALSE; + /* Skip actual entries sent by client */ + return Stream_SafeSeek(s, count * sizeof(UINT64)); } -static void rdp_write_client_font_list_pdu(wStream* s, UINT16 flags) +static BOOL rdp_write_client_font_list_pdu(wStream* s, UINT16 flags) { + if (Stream_GetRemainingCapacity(s) < 8) + return FALSE; Stream_Write_UINT16(s, 0); /* numberFonts (2 bytes) */ Stream_Write_UINT16(s, 0); /* totalNumFonts (2 bytes) */ Stream_Write_UINT16(s, flags); /* listFlags (2 bytes) */ Stream_Write_UINT16(s, 50); /* entrySize (2 bytes) */ + return TRUE; } BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags) { wStream* s = rdp_data_pdu_init(rdp); - rdp_write_client_font_list_pdu(s, flags); + if (!s) + return FALSE; + if (!rdp_write_client_font_list_pdu(s, flags)) + { + Stream_Free(s, TRUE); + return FALSE; + } return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->userId); } @@ -247,8 +330,14 @@ BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp) { - wStream* s; - s = rdp_data_pdu_init(rdp); + wStream* s = rdp_data_pdu_init(rdp); + if (!s) + return FALSE; + if (Stream_GetRemainingCapacity(s) < 8) + { + Stream_Free(s, TRUE); + return FALSE; + } Stream_Write_UINT16(s, 0); /* numberEntries (2 bytes) */ Stream_Write_UINT16(s, 0); /* totalNumEntries (2 bytes) */ Stream_Write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST); /* mapFlags (2 bytes) */ @@ -314,15 +403,18 @@ BOOL rdp_send_deactivate_all(rdpRdp* rdp) { wStream* s = rdp_send_stream_pdu_init(rdp); - BOOL status; + BOOL status = FALSE; if (!s) return FALSE; + if (Stream_GetRemainingCapacity(s) < 7) + goto fail; Stream_Write_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */ Stream_Write_UINT16(s, 1); /* lengthSourceDescriptor (2 bytes) */ Stream_Write_UINT8(s, 0); /* sourceDescriptor (should be 0x00) */ status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->userId); +fail: Stream_Release(s); return status; } @@ -384,3 +476,12 @@ return TRUE; } + +BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp, wStream* s) +{ + if (!rdp_recv_client_persistent_key_list_pdu(s)) + return FALSE; + + // TODO: Actually do something with this + return TRUE; +} diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/activation.h freerdp2-2.3.0+dfsg1/libfreerdp/core/activation.h --- freerdp2-2.2.0+dfsg1/libfreerdp/core/activation.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/activation.h 2021-02-25 08:51:41.000000000 +0000 @@ -55,5 +55,6 @@ FREERDP_LOCAL BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s); FREERDP_LOCAL BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s); +FREERDP_LOCAL BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp, wStream* s); #endif /* FREERDP_LIB_CORE_ACTIVATION_H */ diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/autodetect.c freerdp2-2.3.0+dfsg1/libfreerdp/core/autodetect.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/autodetect.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/autodetect.c 2021-02-25 08:51:41.000000000 +0000 @@ -43,6 +43,10 @@ #define RDP_NETCHAR_SYNC_RESPONSE_TYPE 0x0018 +#define RDP_NETCHAR_RESULTS_0x0840 0x0840U +#define RDP_NETCHAR_RESULTS_0x0880 0x0880U +#define RDP_NETCHAR_RESULTS_0x08C0 0x08C0U + typedef struct { UINT8 headerLength; @@ -59,6 +63,45 @@ UINT16 responseType; } AUTODETECT_RSP_PDU; +static const char* autodetect_request_type_to_string(UINT32 requestType) +{ + switch (requestType) + { + case RDP_RTT_RESPONSE_TYPE: + return "RDP_RTT_RESPONSE_TYPE"; + case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME: + return "RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME"; + case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS: + return "RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS"; + case RDP_RTT_REQUEST_TYPE_CONTINUOUS: + return "RDP_RTT_REQUEST_TYPE_CONTINUOUS"; + case RDP_RTT_REQUEST_TYPE_CONNECTTIME: + return "RDP_RTT_REQUEST_TYPE_CONNECTTIME"; + case RDP_BW_START_REQUEST_TYPE_CONTINUOUS: + return "RDP_BW_START_REQUEST_TYPE_CONTINUOUS"; + case RDP_BW_START_REQUEST_TYPE_TUNNEL: + return "RDP_BW_START_REQUEST_TYPE_TUNNEL"; + case RDP_BW_START_REQUEST_TYPE_CONNECTTIME: + return "RDP_BW_START_REQUEST_TYPE_CONNECTTIME"; + case RDP_BW_PAYLOAD_REQUEST_TYPE: + return "RDP_BW_PAYLOAD_REQUEST_TYPE"; + case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME: + return "RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME"; + case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS: + return "RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS"; + case RDP_BW_STOP_REQUEST_TYPE_TUNNEL: + return "RDP_BW_STOP_REQUEST_TYPE_TUNNEL"; + case RDP_NETCHAR_RESULTS_0x0840: + return "RDP_NETCHAR_RESULTS_0x0840"; + case RDP_NETCHAR_RESULTS_0x0880: + return "RDP_NETCHAR_RESULTS_0x0880"; + case RDP_NETCHAR_RESULTS_0x08C0: + return "RDP_NETCHAR_RESULTS_0x08C0"; + default: + return "UNKNOWN"; + } +} + static BOOL autodetect_send_rtt_measure_request(rdpContext* context, UINT16 sequenceNumber, UINT16 requestType) { @@ -292,10 +335,10 @@ if (context->rdp->autodetect->netCharBandwidth > 0) { - Stream_Write_UINT8(s, 0x12); /* headerLength (1 byte) */ - Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */ - Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */ - Stream_Write_UINT16(s, 0x08C0); /* requestType (2 bytes) */ + Stream_Write_UINT8(s, 0x12); /* headerLength (1 byte) */ + Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */ + Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */ + Stream_Write_UINT16(s, RDP_NETCHAR_RESULTS_0x08C0); /* requestType (2 bytes) */ Stream_Write_UINT32(s, context->rdp->autodetect->netCharBaseRTT); /* baseRTT (4 bytes) */ Stream_Write_UINT32(s, context->rdp->autodetect->netCharBandwidth); /* bandwidth (4 bytes) */ @@ -304,10 +347,10 @@ } else { - Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */ - Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */ - Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */ - Stream_Write_UINT16(s, 0x0840); /* requestType (2 bytes) */ + Stream_Write_UINT8(s, 0x0E); /* headerLength (1 byte) */ + Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */ + Stream_Write_UINT16(s, sequenceNumber); /* sequenceNumber (2 bytes) */ + Stream_Write_UINT16(s, RDP_NETCHAR_RESULTS_0x0840); /* requestType (2 bytes) */ Stream_Write_UINT32(s, context->rdp->autodetect->netCharBaseRTT); /* baseRTT (4 bytes) */ Stream_Write_UINT32(s, context->rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */ @@ -488,7 +531,7 @@ switch (autodetectReqPdu->requestType) { - case 0x0840: + case RDP_NETCHAR_RESULTS_0x0840: /* baseRTT and averageRTT fields are present (bandwidth field is not) */ if ((autodetectReqPdu->headerLength != 0x0E) || (Stream_GetRemainingLength(s) < 8)) @@ -498,7 +541,7 @@ Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */ break; - case 0x0880: + case RDP_NETCHAR_RESULTS_0x0880: /* bandwidth and averageRTT fields are present (baseRTT field is not) */ if ((autodetectReqPdu->headerLength != 0x0E) || (Stream_GetRemainingLength(s) < 8)) @@ -508,7 +551,7 @@ Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */ break; - case 0x08C0: + case RDP_NETCHAR_RESULTS_0x08C0: /* baseRTT, bandwidth, and averageRTT fields are present */ if ((autodetectReqPdu->headerLength != 0x12) || (Stream_GetRemainingLength(s) < 12)) @@ -548,8 +591,23 @@ autodetectReqPdu.headerLength, autodetectReqPdu.headerTypeId, autodetectReqPdu.sequenceNumber, autodetectReqPdu.requestType); + if (!rdp->settings->NetworkAutoDetect) + { + WLog_WARN(AUTODETECT_TAG, + "Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request (RDP_RTT_REQUEST) [%s] " + "message but support was not enabled", + autodetect_request_type_to_string(autodetectReqPdu.requestType)); + } + if (autodetectReqPdu.headerTypeId != TYPE_ID_AUTODETECT_REQUEST) + { + WLog_ERR(AUTODETECT_TAG, + "Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request (RDP_RTT_REQUEST) [%s] " + "message with invalid headerTypeId=0x%04" PRIx16, + autodetect_request_type_to_string(autodetectReqPdu.requestType), + autodetectReqPdu.headerTypeId); return -1; + } switch (autodetectReqPdu.requestType) { @@ -578,9 +636,9 @@ success = autodetect_recv_bandwidth_measure_stop(rdp, s, &autodetectReqPdu); break; - case 0x0840: - case 0x0880: - case 0x08C0: + case RDP_NETCHAR_RESULTS_0x0840: + case RDP_NETCHAR_RESULTS_0x0880: + case RDP_NETCHAR_RESULTS_0x08C0: /* Network Characteristics Result (RDP_NETCHAR_RESULT) - MS-RDPBCGR 2.2.14.1.5 */ success = autodetect_recv_netchar_result(rdp, s, &autodetectReqPdu); break; @@ -610,8 +668,23 @@ autodetectRspPdu.headerLength, autodetectRspPdu.headerTypeId, autodetectRspPdu.sequenceNumber, autodetectRspPdu.responseType); + if (!rdp->settings->NetworkAutoDetect) + { + WLog_WARN(AUTODETECT_TAG, + "Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response (RDP_RTT_RESPONSE) [%s] " + "message but support was not enabled", + autodetect_request_type_to_string(autodetectRspPdu.responseType)); + } + if (autodetectRspPdu.headerTypeId != TYPE_ID_AUTODETECT_RESPONSE) + { + WLog_ERR(AUTODETECT_TAG, + "Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response (RDP_RTT_RESPONSE) [%s] " + "message with invalid headerTypeId=0x%04" PRIx16, + autodetect_request_type_to_string(autodetectRspPdu.responseType), + autodetectRspPdu.headerTypeId); return -1; + } switch (autodetectRspPdu.responseType) { diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/capabilities.c freerdp2-2.3.0+dfsg1/libfreerdp/core/capabilities.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/capabilities.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/capabilities.c 2021-02-25 08:51:41.000000000 +0000 @@ -127,19 +127,22 @@ static size_t rdp_capability_set_start(wStream* s) { size_t header = Stream_GetPosition(s); + if (Stream_GetRemainingCapacity(s) < CAPSET_HEADER_LENGTH) + return SIZE_MAX; Stream_Zero(s, CAPSET_HEADER_LENGTH); return header; } -static void rdp_capability_set_finish(wStream* s, UINT16 header, UINT16 type) +static BOOL rdp_capability_set_finish(wStream* s, UINT16 header, UINT16 type) { - size_t footer; - size_t length; - footer = Stream_GetPosition(s); - length = footer - header; + const size_t footer = Stream_GetPosition(s); + const size_t length = footer - header; + if ((Stream_Capacity(s) < header + 4ULL) || (length > UINT16_MAX)) + return FALSE; Stream_SetPosition(s, header); rdp_write_capability_set_header(s, (UINT16)length, type); Stream_SetPosition(s, footer); + return TRUE; } /** @@ -259,8 +262,7 @@ Stream_Write_UINT16(s, 0); /* generalCompressionLevel (2 bytes) */ Stream_Write_UINT8(s, settings->RefreshRect ? 1 : 0); /* refreshRectSupport (1 byte) */ Stream_Write_UINT8(s, settings->SuppressOutput ? 1 : 0); /* suppressOutputSupport (1 byte) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_GENERAL); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_GENERAL); } #ifdef WITH_DEBUG_CAPABILITIES @@ -410,7 +412,7 @@ */ if ((settings->ColorDepth > UINT16_MAX) || (settings->DesktopWidth > UINT16_MAX) || - (settings->DesktopHeight > UINT16_MAX) || (settings->DesktopResize > UINT16_MAX)) + (settings->DesktopHeight > UINT16_MAX)) return FALSE; if (settings->RdpVersion >= RDP_VERSION_5_PLUS) @@ -431,8 +433,7 @@ Stream_Write_UINT8(s, drawingFlags); /* drawingFlags (1 byte) */ Stream_Write_UINT16(s, 1); /* multipleRectangleSupport (2 bytes) */ Stream_Write_UINT16(s, 0); /* pad2OctetsB (2 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP); } #ifdef WITH_DEBUG_CAPABILITIES @@ -606,8 +607,7 @@ Stream_Write_UINT16(s, 0); /* pad2OctetsD (2 bytes) */ Stream_Write_UINT16(s, textANSICodePage); /* textANSICodePage (2 bytes) */ Stream_Write_UINT16(s, 0); /* pad2OctetsE (2 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_ORDER); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_ORDER); } #ifdef WITH_DEBUG_CAPABILITIES @@ -779,8 +779,7 @@ return FALSE; Stream_Write_UINT16(s, 1000); /* Cache2Entries (2 bytes) */ Stream_Write_UINT16(s, (UINT16)size); /* Cache2MaximumCellSize (2 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP_CACHE); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP_CACHE); } #ifdef WITH_DEBUG_CAPABILITIES @@ -870,8 +869,7 @@ Stream_Write_UINT16(s, 0); /* remoteDetachFlag (2 bytes) */ Stream_Write_UINT16(s, 2); /* controlInterest (2 bytes) */ Stream_Write_UINT16(s, 2); /* detachInterest (2 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_CONTROL); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_CONTROL); } #ifdef WITH_DEBUG_CAPABILITIES @@ -941,8 +939,7 @@ Stream_Write_UINT16(s, 0); /* helpKeyIndexFlag (2 bytes) */ Stream_Write_UINT16(s, 0); /* helpExtendedKeyFlag (2 bytes) */ Stream_Write_UINT16(s, 0); /* windowManagerKeyFlag (2 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_ACTIVATION); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_ACTIVATION); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1038,8 +1035,7 @@ Stream_Write_UINT16(s, (UINT16)settings->PointerCacheSize); /* pointerCacheSize (2 bytes) */ } - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_POINTER); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_POINTER); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1103,8 +1099,7 @@ nodeId = (settings->ServerMode) ? 0x03EA : 0; Stream_Write_UINT16(s, nodeId); /* nodeId (2 bytes) */ Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_SHARE); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_SHARE); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1164,8 +1159,7 @@ return FALSE; Stream_Write_UINT16(s, 6); /* colorTableCacheSize (2 bytes) */ Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_COLOR_CACHE); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_COLOR_CACHE); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1228,8 +1222,7 @@ soundFlags = (settings->SoundBeepsEnabled) ? SOUND_BEEPS_FLAG : 0; Stream_Write_UINT16(s, soundFlags); /* soundFlags (2 bytes) */ Stream_Write_UINT16(s, 0); /* pad2OctetsA (2 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_SOUND); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_SOUND); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1356,8 +1349,7 @@ Stream_Write_UINT32(s, settings->KeyboardSubType); /* keyboardSubType (4 bytes) */ Stream_Write_UINT32(s, settings->KeyboardFunctionKey); /* keyboardFunctionKeys (4 bytes) */ Stream_Zero(s, 64); /* imeFileName (64 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_INPUT); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_INPUT); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1431,8 +1423,7 @@ return FALSE; Stream_Write_UINT16(s, FONTSUPPORT_FONTLIST); /* fontSupportFlags (2 bytes) */ Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_FONT); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_FONT); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1486,8 +1477,7 @@ if (header > UINT16_MAX) return FALSE; Stream_Write_UINT32(s, settings->BrushSupportLevel); /* brushSupportLevel (4 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BRUSH); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BRUSH); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1592,8 +1582,7 @@ rdp_write_cache_definition(s, settings->FragCache); /* fragCache (4 bytes) */ Stream_Write_UINT16(s, (UINT16)settings->GlyphSupportLevel); /* glyphSupportLevel (2 bytes) */ Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_GLYPH_CACHE); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_GLYPH_CACHE); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1704,8 +1693,7 @@ else Stream_Zero(s, 8); - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_OFFSCREEN_CACHE); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_OFFSCREEN_CACHE); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1777,8 +1765,7 @@ Stream_Write_UINT8(s, BITMAP_CACHE_V2); /* cacheVersion (1 byte) */ Stream_Write_UINT8(s, 0); /* pad1 (1 byte) */ Stream_Write_UINT16(s, 0); /* pad2 (2 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP_CACHE_HOST_SUPPORT); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1868,6 +1855,8 @@ return FALSE; header = rdp_capability_set_start(s); + if (header > UINT16_MAX) + return FALSE; cacheFlags = ALLOW_CACHE_WAITING_LIST_FLAG; if (settings->BitmapCachePersistEnabled) @@ -1887,8 +1876,7 @@ rdp_write_bitmap_cache_cell_info( s, &settings->BitmapCacheV2CellInfo[4]); /* bitmapCache4CellInfo (4 bytes) */ Stream_Zero(s, 12); /* pad3 (12 bytes) */ - rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE_V2); - return TRUE; + return rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CACHE_V2); } #ifdef WITH_DEBUG_CAPABILITIES @@ -1979,11 +1967,12 @@ return FALSE; header = rdp_capability_set_start(s); + if (header > UINT16_MAX) + return FALSE; flags = VCCAPS_NO_COMPR; Stream_Write_UINT32(s, flags); /* flags (4 bytes) */ Stream_Write_UINT32(s, settings->VirtualChannelChunkSize); /* VCChunkSize (4 bytes) */ - rdp_capability_set_finish(s, header, CAPSET_TYPE_VIRTUAL_CHANNEL); - return TRUE; + return rdp_capability_set_finish(s, header, CAPSET_TYPE_VIRTUAL_CHANNEL); } #ifdef WITH_DEBUG_CAPABILITIES @@ -2053,14 +2042,15 @@ return FALSE; header = rdp_capability_set_start(s); + if (header > UINT16_MAX) + return FALSE; drawNineGridSupportLevel = (settings->DrawNineGridEnabled) ? DRAW_NINEGRID_SUPPORTED_V2 : DRAW_NINEGRID_NO_SUPPORT; Stream_Write_UINT32(s, drawNineGridSupportLevel); /* drawNineGridSupportLevel (4 bytes) */ Stream_Write_UINT16(s, settings->DrawNineGridCacheSize); /* drawNineGridCacheSize (2 bytes) */ Stream_Write_UINT16( s, settings->DrawNineGridCacheEntries); /* drawNineGridCacheEntries (2 bytes) */ - rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_NINE_GRID_CACHE); - return TRUE; + return rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_NINE_GRID_CACHE); } static void rdp_write_gdiplus_cache_entries(wStream* s, UINT16 gce, UINT16 bce, UINT16 pce, @@ -2158,6 +2148,8 @@ return FALSE; header = rdp_capability_set_start(s); + if (header > UINT16_MAX) + return FALSE; drawGDIPlusSupportLevel = (settings->DrawGdiPlusEnabled) ? DRAW_GDIPLUS_SUPPORTED : DRAW_GDIPLUS_DEFAULT; drawGdiplusCacheLevel = (settings->DrawGdiPlusEnabled) ? DRAW_GDIPLUS_CACHE_LEVEL_ONE @@ -2169,8 +2161,7 @@ rdp_write_gdiplus_cache_chunk_size(s, 512, 2048, 1024, 64); /* GdipCacheChunkSize (8 bytes) */ rdp_write_gdiplus_image_cache_properties(s, 4096, 256, 128); /* GdipImageCacheProperties (6 bytes) */ - rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_GDI_PLUS); - return TRUE; + return rdp_capability_set_finish(s, header, CAPSET_TYPE_DRAW_GDI_PLUS); } #ifdef WITH_DEBUG_CAPABILITIES @@ -2248,6 +2239,8 @@ return FALSE; header = rdp_capability_set_start(s); + if (header > UINT16_MAX) + return FALSE; railSupportLevel = RAIL_LEVEL_SUPPORTED; if (settings->RemoteApplicationSupportLevel & RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED) @@ -2265,8 +2258,7 @@ /* Mask out everything the server does not support. */ railSupportLevel &= settings->RemoteApplicationSupportLevel; Stream_Write_UINT32(s, railSupportLevel); /* railSupportLevel (4 bytes) */ - rdp_capability_set_finish(s, header, CAPSET_TYPE_RAIL); - return TRUE; + return rdp_capability_set_finish(s, header, CAPSET_TYPE_RAIL); } #ifdef WITH_DEBUG_CAPABILITIES @@ -2320,12 +2312,13 @@ return FALSE; header = rdp_capability_set_start(s); + if (header > UINT16_MAX) + return FALSE; Stream_Write_UINT32(s, settings->RemoteWndSupportLevel); /* wndSupportLevel (4 bytes) */ Stream_Write_UINT8(s, settings->RemoteAppNumIconCaches); /* numIconCaches (1 byte) */ Stream_Write_UINT16(s, settings->RemoteAppNumIconCacheEntries); /* numIconCacheEntries (2 bytes) */ - rdp_capability_set_finish(s, header, CAPSET_TYPE_WINDOW); - return TRUE; + return rdp_capability_set_finish(s, header, CAPSET_TYPE_WINDOW); } #ifdef WITH_DEBUG_CAPABILITIES @@ -2383,11 +2376,12 @@ return FALSE; header = rdp_capability_set_start(s); + if (header > UINT16_MAX) + return FALSE; compDeskSupportLevel = (settings->AllowDesktopComposition) ? COMPDESK_SUPPORTED : COMPDESK_NOT_SUPPORTED; Stream_Write_UINT16(s, compDeskSupportLevel); /* compDeskSupportLevel (2 bytes) */ - rdp_capability_set_finish(s, header, CAPSET_TYPE_COMP_DESK); - return TRUE; + return rdp_capability_set_finish(s, header, CAPSET_TYPE_COMP_DESK); } #ifdef WITH_DEBUG_CAPABILITIES @@ -2487,9 +2481,6 @@ { size_t header; - if (!Stream_EnsureRemainingCapacity(s, 32)) - return FALSE; - if (settings->ServerMode && settings->MultifragMaxRequestSize == 0) { /** @@ -2510,10 +2501,13 @@ settings->MultifragMaxRequestSize += 16384; } + if (!Stream_EnsureRemainingCapacity(s, 32)) + return FALSE; header = rdp_capability_set_start(s); + if (header > UINT16_MAX) + return FALSE; Stream_Write_UINT32(s, settings->MultifragMaxRequestSize); /* MaxRequestSize (4 bytes) */ - rdp_capability_set_finish(s, header, CAPSET_TYPE_MULTI_FRAGMENT_UPDATE); - return TRUE; + return rdp_capability_set_finish(s, header, CAPSET_TYPE_MULTI_FRAGMENT_UPDATE); } #ifdef WITH_DEBUG_CAPABILITIES @@ -2576,11 +2570,12 @@ return FALSE; header = rdp_capability_set_start(s); + if (header > UINT16_MAX) + return FALSE; largePointerSupportFlags = settings->LargePointerFlag & (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384); Stream_Write_UINT16(s, largePointerSupportFlags); /* largePointerSupportFlags (2 bytes) */ - rdp_capability_set_finish(s, header, CAPSET_TYPE_LARGE_POINTER); - return TRUE; + return rdp_capability_set_finish(s, header, CAPSET_TYPE_LARGE_POINTER); } #ifdef WITH_DEBUG_CAPABILITIES @@ -2636,6 +2631,8 @@ return FALSE; header = rdp_capability_set_start(s); + if (header > UINT16_MAX) + return FALSE; cmdFlags = SURFCMDS_SET_SURFACE_BITS | SURFCMDS_STREAM_SURFACE_BITS; if (settings->SurfaceFrameMarkerEnabled) @@ -2643,8 +2640,7 @@ Stream_Write_UINT32(s, cmdFlags); /* cmdFlags (4 bytes) */ Stream_Write_UINT32(s, 0); /* reserved (4 bytes) */ - rdp_capability_set_finish(s, header, CAPSET_TYPE_SURFACE_COMMANDS); - return TRUE; + return rdp_capability_set_finish(s, header, CAPSET_TYPE_SURFACE_COMMANDS); } #ifdef WITH_DEBUG_CAPABILITIES @@ -3098,6 +3094,8 @@ return FALSE; header = rdp_capability_set_start(s); + if (header > UINT16_MAX) + return FALSE; bitmapCodecCount = 0; if (settings->RemoteFxCodec) @@ -3202,8 +3200,7 @@ } } - rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CODECS); - return TRUE; + return rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CODECS); } #ifdef WITH_DEBUG_CAPABILITIES @@ -3286,8 +3283,7 @@ if (header > UINT16_MAX) return FALSE; Stream_Write_UINT32(s, settings->FrameAcknowledge); /* (4 bytes) */ - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_FRAME_ACKNOWLEDGE); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_FRAME_ACKNOWLEDGE); } #ifdef WITH_DEBUG_CAPABILITIES @@ -3332,8 +3328,7 @@ if (settings->BitmapCacheV3CodecId > UINT8_MAX) return FALSE; Stream_Write_UINT8(s, (UINT8)settings->BitmapCacheV3CodecId); - rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP_CACHE_V3_CODEC_ID); - return TRUE; + return rdp_capability_set_finish(s, (UINT16)header, CAPSET_TYPE_BITMAP_CACHE_V3_CODEC_ID); } #ifdef WITH_DEBUG_CAPABILITIES diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/codecs.c freerdp2-2.3.0+dfsg1/libfreerdp/core/codecs.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/codecs.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/codecs.c 2021-02-25 08:51:41.000000000 +0000 @@ -31,6 +31,8 @@ { if ((flags & FREERDP_CODEC_INTERLEAVED) && !codecs->interleaved) { + bitmap_interleaved_context_free(codecs->interleaved); + if (!(codecs->interleaved = bitmap_interleaved_context_new(FALSE))) { WLog_ERR(TAG, "Failed to create interleaved codec context"); @@ -40,6 +42,8 @@ if ((flags & FREERDP_CODEC_PLANAR) && !codecs->planar) { + freerdp_bitmap_planar_context_free(codecs->planar); + if (!(codecs->planar = freerdp_bitmap_planar_context_new(FALSE, 64, 64))) { WLog_ERR(TAG, "Failed to create planar bitmap codec context"); @@ -49,6 +53,8 @@ if ((flags & FREERDP_CODEC_NSCODEC) && !codecs->nsc) { + nsc_context_free(codecs->nsc); + if (!(codecs->nsc = nsc_context_new())) { WLog_ERR(TAG, "Failed to create nsc codec context"); @@ -58,6 +64,8 @@ if ((flags & FREERDP_CODEC_REMOTEFX) && !codecs->rfx) { + rfx_context_free(codecs->rfx); + if (!(codecs->rfx = rfx_context_new(FALSE))) { WLog_ERR(TAG, "Failed to create rfx codec context"); @@ -67,6 +75,8 @@ if ((flags & FREERDP_CODEC_CLEARCODEC) && !codecs->clear) { + clear_context_free(codecs->clear); + if (!(codecs->clear = clear_context_new(FALSE))) { WLog_ERR(TAG, "Failed to create clear codec context"); @@ -74,12 +84,14 @@ } } - if (flags & FREERDP_CODEC_ALPHACODEC) + if ((flags & FREERDP_CODEC_ALPHACODEC)) { } if ((flags & FREERDP_CODEC_PROGRESSIVE) && !codecs->progressive) { + progressive_context_free(codecs->progressive); + if (!(codecs->progressive = progressive_context_new(FALSE))) { WLog_ERR(TAG, "Failed to create progressive codec context"); @@ -90,6 +102,8 @@ #ifdef WITH_GFX_H264 if ((flags & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444)) && !codecs->h264) { + h264_context_free(codecs->h264); + if (!(codecs->h264 = h264_context_new(FALSE))) { WLog_ERR(TAG, "Failed to create h264 codec context"); diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/connection.c freerdp2-2.3.0+dfsg1/libfreerdp/core/connection.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/connection.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/connection.c 2021-02-25 08:51:41.000000000 +0000 @@ -1194,6 +1194,14 @@ case CONNECTION_STATE_ACTIVE: rdp->state = CONNECTION_STATE_ACTIVE; + { + ActivatedEventArgs activatedEvent; + rdpContext* context = rdp->context; + EventArgsInit(&activatedEvent, "libfreerdp"); + activatedEvent.firstActivation = !rdp->deactivation_reactivation; + PubSub_OnActivated(context->pubSub, context, &activatedEvent); + } + break; default: @@ -1201,6 +1209,15 @@ break; } + { + ConnectionStateChangeEventArgs stateEvent; + rdpContext* context = rdp->context; + EventArgsInit(&stateEvent, "libfreerdp"); + stateEvent.state = rdp->state; + stateEvent.active = rdp->state == CONNECTION_STATE_ACTIVE; + PubSub_OnConnectionStateChange(context->pubSub, context, &stateEvent); + } + return status; } @@ -1589,3 +1606,10 @@ return "UNKNOWN"; } } + +int rdp_client_get_state(rdpRdp* rdp) +{ + if (!rdp) + return -1; + return rdp->state; +} diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/connection.h freerdp2-2.3.0+dfsg1/libfreerdp/core/connection.h --- freerdp2-2.2.0+dfsg1/libfreerdp/core/connection.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/connection.h 2021-02-25 08:51:41.000000000 +0000 @@ -67,6 +67,7 @@ FREERDP_LOCAL int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s); FREERDP_LOCAL int rdp_client_transition_to_state(rdpRdp* rdp, int state); FREERDP_LOCAL const char* rdp_client_connection_state_string(int state); +FREERDP_LOCAL int rdp_client_get_state(rdpRdp* rdp); FREERDP_LOCAL BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s); FREERDP_LOCAL BOOL rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, wStream* s); diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/errinfo.c freerdp2-2.3.0+dfsg1/libfreerdp/core/errinfo.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/errinfo.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/errinfo.c 2021-02-25 08:51:41.000000000 +0000 @@ -34,8 +34,6 @@ ERRINFO_##_code, "ERRINFO_" #_code, ERRINFO_##_code##_STRING, category \ } -int connectErrorCode; - /* Protocol-independent codes */ #define ERRINFO_RPC_INITIATED_DISCONNECT_STRING \ diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/fastpath.c freerdp2-2.3.0+dfsg1/libfreerdp/core/fastpath.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/fastpath.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/fastpath.c 2021-02-25 08:51:41.000000000 +0000 @@ -317,7 +317,6 @@ return FALSE; Stream_Read_UINT16(s, updateType); /* updateType (2 bytes) */ - switch (updateType) { case UPDATE_TYPE_BITMAP: @@ -934,8 +933,9 @@ return s; } -BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNumEvents) +BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, size_t iNumEvents) { + int state; BOOL rc = FALSE; rdpRdp* rdp; UINT16 length; @@ -944,8 +944,17 @@ if (!s) return FALSE; - if (!fastpath || !fastpath->rdp) + if (!fastpath) + goto fail; + + rdp = fastpath->rdp; + state = rdp_client_get_state(rdp); + if (state != CONNECTION_STATE_ACTIVE) + { + WLog_WARN(TAG, "[%s] called before activation [%s]", __FUNCTION__, + rdp_client_connection_state_string(state)); goto fail; + } /* * A maximum of 15 events are allowed per request @@ -955,7 +964,6 @@ if (iNumEvents > 15) goto fail; - rdp = fastpath->rdp; length = Stream_GetPosition(s); if (length >= (2 << 14)) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/fastpath.h freerdp2-2.3.0+dfsg1/libfreerdp/core/fastpath.h --- freerdp2-2.2.0+dfsg1/libfreerdp/core/fastpath.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/fastpath.h 2021-02-25 08:51:41.000000000 +0000 @@ -160,7 +160,7 @@ FREERDP_LOCAL wStream* fastpath_input_pdu_init(rdpFastPath* fastpath, BYTE eventFlags, BYTE eventCode); FREERDP_LOCAL BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, - int iEventCount); + size_t iEventCount); FREERDP_LOCAL BOOL fastpath_send_input_pdu(rdpFastPath* fastpath, wStream* s); FREERDP_LOCAL wStream* fastpath_update_pdu_init(rdpFastPath* fastpath); diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/freerdp.c freerdp2-2.3.0+dfsg1/libfreerdp/core/freerdp.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/freerdp.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/freerdp.c 2021-02-25 08:51:41.000000000 +0000 @@ -55,8 +55,6 @@ #define TAG FREERDP_TAG("core") -/* connectErrorCode is 'extern' in error.h. See comment there.*/ - UINT freerdp_channel_add_init_handle_data(rdpChannelHandles* handles, void* pInitHandle, void* pUserData) { @@ -163,7 +161,6 @@ /* We always set the return code to 0 before we start the connect sequence*/ instance->ConnectionCallbackState = CLIENT_STATE_INITIAL; - connectErrorCode = 0; freerdp_set_last_error_log(instance->context, FREERDP_ERROR_SUCCESS); clearChannelError(instance->context); ResetEvent(instance->context->abortEvent); @@ -893,61 +890,6 @@ } context->LastError = lastError; - - switch (lastError) - { - case FREERDP_ERROR_PRE_CONNECT_FAILED: - connectErrorCode = PREECONNECTERROR; - break; - - case FREERDP_ERROR_CONNECT_UNDEFINED: - connectErrorCode = UNDEFINEDCONNECTERROR; - break; - - case FREERDP_ERROR_POST_CONNECT_FAILED: - connectErrorCode = POSTCONNECTERROR; - break; - - case FREERDP_ERROR_DNS_ERROR: - connectErrorCode = DNSERROR; - break; - - case FREERDP_ERROR_DNS_NAME_NOT_FOUND: - connectErrorCode = DNSNAMENOTFOUND; - break; - - case FREERDP_ERROR_CONNECT_FAILED: - connectErrorCode = CONNECTERROR; - break; - - case FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR: - connectErrorCode = MCSCONNECTINITIALERROR; - break; - - case FREERDP_ERROR_TLS_CONNECT_FAILED: - connectErrorCode = TLSCONNECTERROR; - break; - - case FREERDP_ERROR_AUTHENTICATION_FAILED: - connectErrorCode = AUTHENTICATIONERROR; - break; - - case FREERDP_ERROR_INSUFFICIENT_PRIVILEGES: - connectErrorCode = INSUFFICIENTPRIVILEGESERROR; - break; - - case FREERDP_ERROR_CONNECT_CANCELLED: - connectErrorCode = CANCELEDBYUSER; - break; - - case FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED: - connectErrorCode = CONNECTERROR; - break; - - case FREERDP_ERROR_CONNECT_TRANSPORT_FAILED: - connectErrorCode = CONNECTERROR; - break; - } } const char* freerdp_get_logon_error_info_type(UINT32 type) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/http.c freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/http.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/http.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/http.c 2021-02-25 08:51:41.000000000 +0000 @@ -30,6 +30,9 @@ #include +/* websocket need sha1 for Sec-Websocket-Accept */ +#include + #ifdef HAVE_VALGRIND_MEMCHECK_H #include #endif @@ -40,6 +43,8 @@ #define RESPONSE_SIZE_LIMIT 64 * 1024 * 1024 +#define WEBSOCKET_MAGIC_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" + struct _http_context { char* Method; @@ -52,6 +57,8 @@ char* Pragma; char* RdgConnectionId; char* RdgAuthScheme; + BOOL websocketUpgrade; + char SecWebsocketKey[16]; }; struct _http_request @@ -63,7 +70,7 @@ char* Authorization; size_t ContentLength; char* Content; - char* TransferEncoding; + TRANSFER_ENCODING TransferEncoding; }; struct _http_response @@ -76,6 +83,9 @@ size_t ContentLength; const char* ContentType; + TRANSFER_ENCODING TransferEncoding; + const char* SecWebsocketVersion; + const char* SecWebsocketAccept; size_t BodyLength; BYTE* BodyContent; @@ -258,6 +268,30 @@ return TRUE; } +BOOL http_context_enable_websocket_upgrade(HttpContext* context, BOOL enable) +{ + if (!context) + return FALSE; + + if (enable) + { + int i; + winpr_RAND((BYTE*)context->SecWebsocketKey, 15); + for (i = 0; i < 16; i++) + context->SecWebsocketKey[i] = (context->SecWebsocketKey[i] | 0x40) & 0x5f; + context->SecWebsocketKey[15] = '\0'; + } + else + context->SecWebsocketKey[0] = '\0'; + context->websocketUpgrade = enable; + return TRUE; +} + +BOOL http_context_is_websocket_upgrade_enabled(HttpContext* context) +{ + return context->websocketUpgrade; +} + BOOL http_context_set_rdg_auth_scheme(HttpContext* context, const char* RdgAuthScheme) { if (!context || !RdgAuthScheme) @@ -342,16 +376,12 @@ return TRUE; } -BOOL http_request_set_transfer_encoding(HttpRequest* request, const char* TransferEncoding) +BOOL http_request_set_transfer_encoding(HttpRequest* request, TRANSFER_ENCODING TransferEncoding) { - if (!request || !TransferEncoding) + if (!request || TransferEncoding == TransferEncodingUnknown) return FALSE; - free(request->TransferEncoding); - request->TransferEncoding = _strdup(TransferEncoding); - - if (!request->TransferEncoding) - return FALSE; + request->TransferEncoding = TransferEncoding; return TRUE; } @@ -429,13 +459,26 @@ if (!http_encode_header_line(s, request->Method, request->URI) || !http_encode_body_line(s, "Cache-Control", context->CacheControl) || - !http_encode_body_line(s, "Connection", context->Connection) || !http_encode_body_line(s, "Pragma", context->Pragma) || !http_encode_body_line(s, "Accept", context->Accept) || !http_encode_body_line(s, "User-Agent", context->UserAgent) || !http_encode_body_line(s, "Host", context->Host)) goto fail; + if (!context->websocketUpgrade) + { + if (!http_encode_body_line(s, "Connection", context->Connection)) + goto fail; + } + else + { + if (!http_encode_body_line(s, "Connection", "Upgrade") || + !http_encode_body_line(s, "Upgrade", "websocket") || + !http_encode_body_line(s, "Sec-Websocket-Version", "13") || + !http_encode_body_line(s, "Sec-Websocket-Key", context->SecWebsocketKey)) + goto fail; + } + if (context->RdgConnectionId) { if (!http_encode_body_line(s, "RDG-Connection-Id", context->RdgConnectionId)) @@ -448,9 +491,14 @@ goto fail; } - if (request->TransferEncoding) + if (request->TransferEncoding != TransferEncodingIdentity) { - if (!http_encode_body_line(s, "Transfer-Encoding", request->TransferEncoding)) + if (request->TransferEncoding == TransferEncodingChunked) + { + if (!http_encode_body_line(s, "Transfer-Encoding", "chunked")) + goto fail; + } + else goto fail; } else @@ -480,7 +528,12 @@ HttpRequest* http_request_new(void) { - return (HttpRequest*)calloc(1, sizeof(HttpRequest)); + HttpRequest* request = (HttpRequest*)calloc(1, sizeof(HttpRequest)); + if (!request) + return NULL; + + request->TransferEncoding = TransferEncodingIdentity; + return request; } void http_request_free(HttpRequest* request) @@ -494,7 +547,6 @@ free(request->Content); free(request->Method); free(request->URI); - free(request->TransferEncoding); free(request); } @@ -550,7 +602,6 @@ const char* value) { BOOL status = TRUE; - if (!response || !name) return FALSE; @@ -572,6 +623,29 @@ if (!response->ContentType) return FALSE; } + else if (_stricmp(name, "Transfer-Encoding") == 0) + { + if (_stricmp(value, "identity") == 0) + response->TransferEncoding = TransferEncodingIdentity; + else if (_stricmp(value, "chunked") == 0) + response->TransferEncoding = TransferEncodingChunked; + else + response->TransferEncoding = TransferEncodingUnknown; + } + else if (_stricmp(name, "Sec-WebSocket-Version") == 0) + { + response->SecWebsocketVersion = value; + + if (!response->SecWebsocketVersion) + return FALSE; + } + else if (_stricmp(name, "Sec-WebSocket-Accept") == 0) + { + response->SecWebsocketAccept = value; + + if (!response->SecWebsocketAccept) + return FALSE; + } else if (_stricmp(name, "WWW-Authenticate") == 0) { char* separator = NULL; @@ -948,6 +1022,8 @@ ListDictionary_KeyObject(response->Authenticates)->fnObjectEquals = strings_equals_nocase; ListDictionary_ValueObject(response->Authenticates)->fnObjectEquals = strings_equals_nocase; + + response->TransferEncoding = TransferEncodingIdentity; return response; fail: http_response_free(response); @@ -1006,13 +1082,74 @@ return (SSIZE_T)response->BodyLength; } -const char* http_response_get_auth_token(HttpResponse* respone, const char* method) +const char* http_response_get_auth_token(HttpResponse* response, const char* method) { - if (!respone || !method) + if (!response || !method) return NULL; - if (!ListDictionary_Contains(respone->Authenticates, method)) + if (!ListDictionary_Contains(response->Authenticates, method)) return NULL; - return ListDictionary_GetItemValue(respone->Authenticates, method); + return ListDictionary_GetItemValue(response->Authenticates, method); +} + +TRANSFER_ENCODING http_response_get_transfer_encoding(HttpResponse* response) +{ + if (!response) + return TransferEncodingUnknown; + + return response->TransferEncoding; +} + +BOOL http_response_is_websocket(HttpContext* http, HttpResponse* response) +{ + BOOL isWebsocket = FALSE; + WINPR_DIGEST_CTX* sha1 = NULL; + char* base64accept = NULL; + BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; + + if (!http || !response) + return FALSE; + + if (!http->websocketUpgrade || response->StatusCode != HTTP_STATUS_SWITCH_PROTOCOLS) + return FALSE; + + if (response->SecWebsocketVersion && _stricmp(response->SecWebsocketVersion, "13") != 0) + return FALSE; + + if (!response->SecWebsocketAccept) + return FALSE; + + /* now check if Sec-Websocket-Accept is correct */ + + sha1 = winpr_Digest_New(); + if (!sha1) + goto out; + + if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1)) + goto out; + + if (!winpr_Digest_Update(sha1, (const BYTE*)http->SecWebsocketKey, + strlen(http->SecWebsocketKey))) + goto out; + if (!winpr_Digest_Update(sha1, (const BYTE*)WEBSOCKET_MAGIC_GUID, strlen(WEBSOCKET_MAGIC_GUID))) + goto out; + + if (!winpr_Digest_Final(sha1, sha1_digest, sizeof(sha1_digest))) + goto out; + + base64accept = crypto_base64_encode(sha1_digest, WINPR_SHA1_DIGEST_LENGTH); + if (!base64accept) + goto out; + + if (_stricmp(response->SecWebsocketAccept, base64accept) != 0) + { + WLog_WARN(TAG, "Webserver gave Websocket Upgrade response but sanity check failed"); + goto out; + } + isWebsocket = TRUE; +out: + winpr_Digest_Free(sha1); + free(base64accept); + return isWebsocket; } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/http.h freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/http.h --- freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/http.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/http.h 2021-02-25 08:51:41.000000000 +0000 @@ -26,6 +26,13 @@ #include #include +typedef enum _TRANSFER_ENCODING +{ + TransferEncodingUnknown, + TransferEncodingIdentity, + TransferEncodingChunked +} TRANSFER_ENCODING; + /* HTTP context */ typedef struct _http_context HttpContext; @@ -45,6 +52,8 @@ const char* RdgConnectionId); FREERDP_LOCAL BOOL http_context_set_rdg_auth_scheme(HttpContext* context, const char* RdgAuthScheme); +FREERDP_LOCAL BOOL http_context_enable_websocket_upgrade(HttpContext* context, BOOL enable); +FREERDP_LOCAL BOOL http_context_is_websocket_upgrade_enabled(HttpContext* context); /* HTTP request */ typedef struct _http_request HttpRequest; @@ -61,7 +70,7 @@ FREERDP_LOCAL BOOL http_request_set_auth_scheme(HttpRequest* request, const char* AuthScheme); FREERDP_LOCAL BOOL http_request_set_auth_param(HttpRequest* request, const char* AuthParam); FREERDP_LOCAL BOOL http_request_set_transfer_encoding(HttpRequest* request, - const char* TransferEncoding); + TRANSFER_ENCODING TransferEncoding); FREERDP_LOCAL wStream* http_request_write(HttpContext* context, HttpRequest* request); @@ -76,6 +85,8 @@ FREERDP_LOCAL long http_response_get_status_code(HttpResponse* response); FREERDP_LOCAL SSIZE_T http_response_get_body_length(HttpResponse* response); -FREERDP_LOCAL const char* http_response_get_auth_token(HttpResponse* respone, const char* method); +FREERDP_LOCAL const char* http_response_get_auth_token(HttpResponse* response, const char* method); +FREERDP_LOCAL TRANSFER_ENCODING http_response_get_transfer_encoding(HttpResponse* response); +FREERDP_LOCAL BOOL http_response_is_websocket(HttpContext* http, HttpResponse* response); #endif /* FREERDP_LIB_CORE_GATEWAY_HTTP_H */ diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rdg.c freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/rdg.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rdg.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/rdg.c 2021-02-25 08:51:41.000000000 +0000 @@ -104,6 +104,67 @@ #define HTTP_CAPABILITY_REAUTH 0x10 #define HTTP_CAPABILITY_UDP_TRANSPORT 0x20 +#define WEBSOCKET_MASK_BIT 0x80 +#define WEBSOCKET_FIN_BIT 0x80 + +typedef enum _WEBSOCKET_OPCODE +{ + WebsocketContinuationOpcode = 0x0, + WebsocketTextOpcode = 0x1, + WebsocketBinaryOpcode = 0x2, + WebsocketCloseOpcode = 0x8, + WebsocketPingOpcode = 0x9, + WebsocketPongOpcode = 0xa, +} WEBSOCKET_OPCODE; + +typedef enum _WEBSOCKET_STATE +{ + WebsocketStateOpcodeAndFin, + WebsocketStateLengthAndMasking, + WebsocketStateShortLength, + WebsocketStateLongLength, + WebSocketStateMaskingKey, + WebSocketStatePayload, +} WEBSOCKET_STATE; + +typedef struct +{ + size_t payloadLength; + uint32_t maskingKey; + BOOL masking; + BOOL closeSent; + BYTE opcode; + BYTE fragmentOriginalOpcode; + BYTE lengthAndMaskPosition; + WEBSOCKET_STATE state; + wStream* responseStreamBuffer; +} rdg_http_websocket_context; +typedef enum _CHUNK_STATE +{ + ChunkStateLenghHeader, + ChunkStateData, + ChunkStateFooter +} CHUNK_STATE; + +typedef struct +{ + size_t nextOffset; + size_t headerFooterPos; + CHUNK_STATE state; + char lenBuffer[11]; +} rdg_http_encoding_chunked_context; + +typedef struct +{ + TRANSFER_ENCODING httpTransferEncoding; + BOOL isWebsocketTransport; + union _context + { + rdg_http_encoding_chunked_context chunked; + rdg_http_websocket_context websocket; + } context; +} rdg_http_encoding_context; + struct rdp_rdg { rdpContext* context; @@ -124,6 +185,7 @@ int timeout; UINT16 extAuth; UINT16 reserved2; + rdg_http_encoding_context transferEncoding; }; enum @@ -151,22 +213,22 @@ { UINT32 code; const char* name; -} t_err_mapping; +} t_flag_mapping; -static const t_err_mapping tunnel_response_fields_present[] = { +static const t_flag_mapping tunnel_response_fields_present[] = { { HTTP_TUNNEL_RESPONSE_FIELD_TUNNEL_ID, "HTTP_TUNNEL_RESPONSE_FIELD_TUNNEL_ID" }, { HTTP_TUNNEL_RESPONSE_FIELD_CAPS, "HTTP_TUNNEL_RESPONSE_FIELD_CAPS" }, { HTTP_TUNNEL_RESPONSE_FIELD_SOH_REQ, "HTTP_TUNNEL_RESPONSE_FIELD_SOH_REQ" }, { HTTP_TUNNEL_RESPONSE_FIELD_CONSENT_MSG, "HTTP_TUNNEL_RESPONSE_FIELD_CONSENT_MSG" } }; -static const t_err_mapping channel_response_fields_present[] = { +static const t_flag_mapping channel_response_fields_present[] = { { HTTP_CHANNEL_RESPONSE_FIELD_CHANNELID, "HTTP_CHANNEL_RESPONSE_FIELD_CHANNELID" }, { HTTP_CHANNEL_RESPONSE_OPTIONAL, "HTTP_CHANNEL_RESPONSE_OPTIONAL" }, { HTTP_CHANNEL_RESPONSE_FIELD_UDPPORT, "HTTP_CHANNEL_RESPONSE_FIELD_UDPPORT" } }; -static const t_err_mapping tunnel_authorization_response_fields_present[] = { +static const t_flag_mapping tunnel_authorization_response_fields_present[] = { { HTTP_TUNNEL_AUTH_RESPONSE_FIELD_REDIR_FLAGS, "HTTP_TUNNEL_AUTH_RESPONSE_FIELD_REDIR_FLAGS" }, { HTTP_TUNNEL_AUTH_RESPONSE_FIELD_IDLE_TIMEOUT, "HTTP_TUNNEL_AUTH_RESPONSE_FIELD_IDLE_TIMEOUT" }, @@ -174,15 +236,23 @@ "HTTP_TUNNEL_AUTH_RESPONSE_FIELD_SOH_RESPONSE" } }; -static const t_err_mapping extended_auth[] = { +static const t_flag_mapping extended_auth[] = { { HTTP_EXTENDED_AUTH_NONE, "HTTP_EXTENDED_AUTH_NONE" }, { HTTP_EXTENDED_AUTH_SC, "HTTP_EXTENDED_AUTH_SC" }, { HTTP_EXTENDED_AUTH_PAA, "HTTP_EXTENDED_AUTH_PAA" }, { HTTP_EXTENDED_AUTH_SSPI_NTLM, "HTTP_EXTENDED_AUTH_SSPI_NTLM" } }; -static const char* fields_present_to_string(UINT16 fieldsPresent, const t_err_mapping* map, - size_t elements) +static const t_flag_mapping capabilities_enum[] = { + { HTTP_CAPABILITY_TYPE_QUAR_SOH, "HTTP_CAPABILITY_TYPE_QUAR_SOH" }, + { HTTP_CAPABILITY_IDLE_TIMEOUT, "HTTP_CAPABILITY_IDLE_TIMEOUT" }, + { HTTP_CAPABILITY_MESSAGING_CONSENT_SIGN, "HTTP_CAPABILITY_MESSAGING_CONSENT_SIGN" }, + { HTTP_CAPABILITY_MESSAGING_SERVICE_MSG, "HTTP_CAPABILITY_MESSAGING_SERVICE_MSG" }, + { HTTP_CAPABILITY_REAUTH, "HTTP_CAPABILITY_REAUTH" }, + { HTTP_CAPABILITY_UDP_TRANSPORT, "HTTP_CAPABILITY_UDP_TRANSPORT" } +}; + +static const char* flags_to_string(UINT32 flags, const t_flag_mapping* map, size_t elements) { size_t x = 0; static char buffer[1024] = { 0 }; @@ -194,31 +264,31 @@ if (buffer[0] != '\0') strcat(buffer, "|"); - if ((map[x].code & fieldsPresent) != 0) + if ((map[x].code & flags) != 0) strcat(buffer, map[x].name); } - sprintf_s(fields, ARRAYSIZE(fields), " [%04" PRIx16 "]", fieldsPresent); + sprintf_s(fields, ARRAYSIZE(fields), " [%04" PRIx32 "]", flags); strcat(buffer, fields); return buffer; } static const char* channel_response_fields_present_to_string(UINT16 fieldsPresent) { - return fields_present_to_string(fieldsPresent, channel_response_fields_present, - ARRAYSIZE(channel_response_fields_present)); + return flags_to_string(fieldsPresent, channel_response_fields_present, + ARRAYSIZE(channel_response_fields_present)); } static const char* tunnel_response_fields_present_to_string(UINT16 fieldsPresent) { - return fields_present_to_string(fieldsPresent, tunnel_response_fields_present, - ARRAYSIZE(tunnel_response_fields_present)); + return flags_to_string(fieldsPresent, tunnel_response_fields_present, + ARRAYSIZE(tunnel_response_fields_present)); } static const char* tunnel_authorization_response_fields_present_to_string(UINT16 fieldsPresent) { - return fields_present_to_string(fieldsPresent, tunnel_authorization_response_fields_present, - ARRAYSIZE(tunnel_authorization_response_fields_present)); + return flags_to_string(fieldsPresent, tunnel_authorization_response_fields_present, + ARRAYSIZE(tunnel_authorization_response_fields_present)); } static const char* extended_auth_to_string(UINT16 auth) @@ -226,12 +296,43 @@ if (auth == HTTP_EXTENDED_AUTH_NONE) return "HTTP_EXTENDED_AUTH_NONE [0x0000]"; - return fields_present_to_string(auth, extended_auth, ARRAYSIZE(extended_auth)); + return flags_to_string(auth, extended_auth, ARRAYSIZE(extended_auth)); } -static BOOL rdg_write_packet(rdpRdg* rdg, wStream* sPacket) +static const char* capabilities_enum_to_string(UINT32 capabilities) +{ + return flags_to_string(capabilities, capabilities_enum, ARRAYSIZE(capabilities_enum)); +} + +static BOOL rdg_read_http_unicode_string(wStream* s, const WCHAR** string, UINT16* lengthInBytes) +{ + WCHAR* str; + UINT16 strLenBytes; + + /* Read length of the string */ + if (Stream_GetRemainingLength(s) < 4) + return FALSE; + Stream_Read_UINT16(s, strLenBytes); + + /* Remember position of our string */ + str = (WCHAR*)Stream_Pointer(s); + + /* seek past the string - if this fails something is wrong */ + if (!Stream_SafeSeek(s, strLenBytes)) + return FALSE; + + /* return the string data (if wanted) */ + if (string) + *string = str; + if (lengthInBytes) + *lengthInBytes = strLenBytes; + + return TRUE; +} + +static BOOL rdg_write_chunked(BIO* bio, wStream* sPacket) { - size_t s; + size_t len; int status; wStream* sChunk; char chunkSize[11]; @@ -245,35 +346,551 @@ Stream_Write(sChunk, Stream_Buffer(sPacket), Stream_Length(sPacket)); Stream_Write(sChunk, "\r\n", 2); Stream_SealLength(sChunk); - s = Stream_Length(sChunk); + len = Stream_Length(sChunk); - if (s > INT_MAX) + if (len > INT_MAX) return FALSE; - status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), (int)s); + status = BIO_write(bio, Stream_Buffer(sChunk), (int)len); Stream_Free(sChunk, TRUE); + if (status != len) + return FALSE; + + return TRUE; +} + +static BOOL rdg_write_websocket(BIO* bio, wStream* sPacket, WEBSOCKET_OPCODE opcode) +{ + size_t len; + size_t fullLen; + int status; + wStream* sWS; + + uint32_t maskingKey; + + size_t streamPos; + + len = Stream_Length(sPacket); + Stream_SetPosition(sPacket, 0); + + if (len > INT_MAX) + return FALSE; + + if (len < 126) + fullLen = len + 6; /* 2 byte "mini header" + 4 byte masking key */ + else if (len < 0x10000) + fullLen = len + 8; /* 2 byte "mini header" + 2 byte length + 4 byte masking key */ + else + fullLen = len + 14; /* 2 byte "mini header" + 8 byte length + 4 byte masking key */ + + sWS = Stream_New(NULL, fullLen); + if (!sWS) + return FALSE; + + winpr_RAND((BYTE*)&maskingKey, 4); + + Stream_Write_UINT8(sWS, WEBSOCKET_FIN_BIT | opcode); + if (len < 126) + Stream_Write_UINT8(sWS, len | WEBSOCKET_MASK_BIT); + else if (len < 0x10000) + { + Stream_Write_UINT8(sWS, 126 | WEBSOCKET_MASK_BIT); + Stream_Write_UINT16_BE(sWS, len); + } + else + { + Stream_Write_UINT8(sWS, 127 | WEBSOCKET_MASK_BIT); + Stream_Write_UINT32_BE(sWS, 0); /* payload is limited to INT_MAX */ + Stream_Write_UINT32_BE(sWS, len); + } + Stream_Write_UINT32(sWS, maskingKey); + + /* mask as much as possible with 32bit access */ + for (streamPos = 0; streamPos + 4 <= len; streamPos += 4) + { + uint32_t data; + Stream_Read_UINT32(sPacket, data); + Stream_Write_UINT32(sWS, data ^ maskingKey); + } + + /* mask the rest byte by byte */ + for (; streamPos < len; streamPos++) + { + BYTE data; + BYTE* partialMask = ((BYTE*)&maskingKey) + (streamPos % 4); + Stream_Read_UINT8(sPacket, data); + Stream_Write_UINT8(sWS, data ^ *partialMask); + } + + Stream_SealLength(sWS); + + status = BIO_write(bio, Stream_Buffer(sWS), Stream_Length(sWS)); + Stream_Free(sWS, TRUE); + + if (status != fullLen) + return FALSE; + + return TRUE; +} + +static BOOL rdg_write_packet(rdpRdg* rdg, wStream* sPacket) +{ + if (rdg->transferEncoding.isWebsocketTransport) + { + if (rdg->transferEncoding.context.websocket.closeSent) + return FALSE; + return rdg_write_websocket(rdg->tlsOut->bio, sPacket, WebsocketBinaryOpcode); + } + + return rdg_write_chunked(rdg->tlsIn->bio, sPacket); +} + +static int rdg_websocket_read_data(BIO* bio, BYTE* pBuffer, size_t size, + rdg_http_websocket_context* encodingContext) +{ + int status; + + if (encodingContext->payloadLength == 0) + { + encodingContext->state = WebsocketStateOpcodeAndFin; + return 0; + } + + status = + BIO_read(bio, pBuffer, + (encodingContext->payloadLength < size ? encodingContext->payloadLength : size)); + if (status <= 0) + return status; + + encodingContext->payloadLength -= status; + + if (encodingContext->payloadLength == 0) + encodingContext->state = WebsocketStateOpcodeAndFin; + + return status; +} + +static int rdg_websocket_read_discard(BIO* bio, rdg_http_websocket_context* encodingContext) +{ + char _dummy[256]; + int status; + + if (encodingContext->payloadLength == 0) + { + encodingContext->state = WebsocketStateOpcodeAndFin; + return 0; + } + + status = BIO_read(bio, _dummy, sizeof(_dummy)); + if (status <= 0) + return status; + + encodingContext->payloadLength -= status; + + if (encodingContext->payloadLength == 0) + encodingContext->state = WebsocketStateOpcodeAndFin; + + return status; +} + +static int rdg_websocket_read_wstream(BIO* bio, wStream* s, + rdg_http_websocket_context* encodingContext) +{ + int status; + + if (encodingContext->payloadLength == 0) + { + encodingContext->state = WebsocketStateOpcodeAndFin; + return 0; + } + if (s == NULL || Stream_GetRemainingCapacity(s) != encodingContext->payloadLength) + return -1; + + status = BIO_read(bio, Stream_Pointer(s), encodingContext->payloadLength); + if (status <= 0) + return status; + + Stream_Seek(s, status); + + encodingContext->payloadLength -= status; + + if (encodingContext->payloadLength == 0) + { + encodingContext->state = WebsocketStateOpcodeAndFin; + Stream_SealLength(s); + Stream_SetPosition(s, 0); + } + + return status; +} + +static BOOL rdg_websocket_reply_close(BIO* bio, wStream* s) +{ + /* write back close */ + wStream* closeFrame; + uint16_t maskingKey1; + uint16_t maskingKey2; + int status; + size_t closeDataLen; + + closeDataLen = 0; + if (s != NULL && Stream_Length(s) >= 2) + closeDataLen = 2; + + closeFrame = Stream_New(NULL, 6 + closeDataLen); + Stream_Write_UINT8(closeFrame, WEBSOCKET_FIN_BIT | WebsocketPongOpcode); + Stream_Write_UINT8(closeFrame, closeDataLen | WEBSOCKET_MASK_BIT); /* no payload */ + winpr_RAND((BYTE*)&maskingKey1, 2); + winpr_RAND((BYTE*)&maskingKey2, 2); + Stream_Write_UINT16(closeFrame, maskingKey1); + Stream_Write_UINT16(closeFrame, maskingKey2); /* unused half, max 2 bytes of data */ + + if (closeDataLen == 2) + { + uint16_t data; + Stream_Read_UINT16(s, data); + Stream_Write_UINT16(s, data ^ maskingKey1); + } + Stream_SealLength(closeFrame); + + status = BIO_write(bio, Stream_Buffer(closeFrame), Stream_Length(closeFrame)); + /* server MUST close socket now. The server is not allowed anymore to + * send frames but if he does, nothing bad would happen */ if (status < 0) return FALSE; + return TRUE; +} + +static BOOL rdg_websocket_reply_pong(BIO* bio, wStream* s) +{ + wStream* closeFrame; + uint32_t maskingKey; + int status; + + if (s != NULL) + return rdg_write_websocket(bio, s, WebsocketPongOpcode); + closeFrame = Stream_New(NULL, 6); + Stream_Write_UINT8(closeFrame, WEBSOCKET_FIN_BIT | WebsocketPongOpcode); + Stream_Write_UINT8(closeFrame, 0 | WEBSOCKET_MASK_BIT); /* no payload */ + winpr_RAND((BYTE*)&maskingKey, 4); + Stream_Write_UINT32(closeFrame, maskingKey); /* dummy masking key. */ + Stream_SealLength(closeFrame); + + status = BIO_write(bio, Stream_Buffer(closeFrame), Stream_Length(closeFrame)); + + if (status < 0) + return FALSE; return TRUE; } -static BOOL rdg_read_all(rdpTls* tls, BYTE* buffer, int size) +static int rdg_websocket_handle_payload(BIO* bio, BYTE* pBuffer, size_t size, + rdg_http_websocket_context* encodingContext) +{ + int status; + BYTE effectiveOpcode = ((encodingContext->opcode & 0xf) == WebsocketContinuationOpcode + ? encodingContext->fragmentOriginalOpcode & 0xf + : encodingContext->opcode & 0xf); + + switch (effectiveOpcode) + { + case WebsocketBinaryOpcode: + { + status = rdg_websocket_read_data(bio, pBuffer, size, encodingContext); + if (status < 0) + return status; + + return status; + } + break; + case WebsocketPingOpcode: + { + if (encodingContext->responseStreamBuffer == NULL) + encodingContext->responseStreamBuffer = + Stream_New(NULL, encodingContext->payloadLength); + + status = rdg_websocket_read_wstream(bio, encodingContext->responseStreamBuffer, + encodingContext); + if (status < 0) + return status; + + if (encodingContext->payloadLength == 0) + { + if (!encodingContext->closeSent) + rdg_websocket_reply_pong(bio, encodingContext->responseStreamBuffer); + + if (encodingContext->responseStreamBuffer) + Stream_Free(encodingContext->responseStreamBuffer, TRUE); + encodingContext->responseStreamBuffer = NULL; + } + } + break; + case WebsocketCloseOpcode: + { + if (encodingContext->responseStreamBuffer == NULL) + encodingContext->responseStreamBuffer = + Stream_New(NULL, encodingContext->payloadLength); + + status = rdg_websocket_read_wstream(bio, encodingContext->responseStreamBuffer, + encodingContext); + if (status < 0) + return status; + + if (encodingContext->payloadLength == 0) + { + rdg_websocket_reply_close(bio, encodingContext->responseStreamBuffer); + encodingContext->closeSent = TRUE; + + if (encodingContext->responseStreamBuffer) + Stream_Free(encodingContext->responseStreamBuffer, TRUE); + encodingContext->responseStreamBuffer = NULL; + } + } + break; + default: + WLog_WARN(TAG, "Unimplemented websocket opcode %x. Dropping", effectiveOpcode & 0xf); + + status = rdg_websocket_read_discard(bio, encodingContext); + if (status < 0) + return status; + } + /* return how many bytes have been written to pBuffer. + * Only WebsocketBinaryOpcode writes into it and it returns directly */ + return 0; +} + +static int rdg_websocket_read(BIO* bio, BYTE* pBuffer, size_t size, + rdg_http_websocket_context* encodingContext) +{ + int status; + int effectiveDataLen = 0; + assert(encodingContext != NULL); + while (TRUE) + { + switch (encodingContext->state) + { + case WebsocketStateOpcodeAndFin: + { + BYTE buffer[1]; + status = BIO_read(bio, (char*)buffer, 1); + if (status <= 0) + return (effectiveDataLen > 0 ? effectiveDataLen : status); + + encodingContext->opcode = buffer[0]; + if (((encodingContext->opcode & 0xf) != WebsocketContinuationOpcode) && + (encodingContext->opcode & 0xf) < 0x08) + encodingContext->fragmentOriginalOpcode = encodingContext->opcode; + encodingContext->state = WebsocketStateLengthAndMasking; + } + break; + case WebsocketStateLengthAndMasking: + { + BYTE buffer[1]; + BYTE len; + status = BIO_read(bio, (char*)buffer, 1); + if (status <= 0) + return (effectiveDataLen > 0 ? effectiveDataLen : status); + + encodingContext->masking = ((buffer[0] & WEBSOCKET_MASK_BIT) == WEBSOCKET_MASK_BIT); + encodingContext->lengthAndMaskPosition = 0; + encodingContext->payloadLength = 0; + len = buffer[0] & 0x7f; + if (len < 126) + { + encodingContext->payloadLength = len; + encodingContext->state = (encodingContext->masking ? WebSocketStateMaskingKey + : WebSocketStatePayload); + } + else if (len == 126) + encodingContext->state = WebsocketStateShortLength; + else + encodingContext->state = WebsocketStateLongLength; + } + break; + case WebsocketStateShortLength: + case WebsocketStateLongLength: + { + BYTE buffer[1]; + BYTE lenLength = (encodingContext->state == WebsocketStateShortLength ? 2 : 8); + while (encodingContext->lengthAndMaskPosition < lenLength) + { + status = BIO_read(bio, (char*)buffer, 1); + if (status <= 0) + return (effectiveDataLen > 0 ? effectiveDataLen : status); + + encodingContext->payloadLength = + (encodingContext->payloadLength) << 8 | buffer[0]; + encodingContext->lengthAndMaskPosition += status; + } + encodingContext->state = + (encodingContext->masking ? WebSocketStateMaskingKey : WebSocketStatePayload); + } + break; + case WebSocketStateMaskingKey: + { + WLog_WARN( + TAG, "Websocket Server sends data with masking key. This is against RFC 6455."); + return -1; + } + break; + case WebSocketStatePayload: + { + status = rdg_websocket_handle_payload(bio, pBuffer, size, encodingContext); + if (status < 0) + return (effectiveDataLen > 0 ? effectiveDataLen : status); + + effectiveDataLen += status; + + if ((size_t)status == size) + return effectiveDataLen; + pBuffer += status; + size -= status; + } + } + } + /* should be unreachable */ + return -1; +} +static int rdg_chuncked_read(BIO* bio, BYTE* pBuffer, size_t size, + rdg_http_encoding_chunked_context* encodingContext) { int status; - int readCount = 0; + int effectiveDataLen = 0; + assert(encodingContext != NULL); + while (TRUE) + { + switch (encodingContext->state) + { + case ChunkStateData: + { + status = BIO_read( + bio, pBuffer, + (size > encodingContext->nextOffset ? encodingContext->nextOffset : size)); + if (status <= 0) + return (effectiveDataLen > 0 ? effectiveDataLen : status); + + encodingContext->nextOffset -= status; + if (encodingContext->nextOffset == 0) + { + encodingContext->state = ChunkStateFooter; + encodingContext->headerFooterPos = 0; + } + effectiveDataLen += status; + + if ((size_t)status == size) + return effectiveDataLen; + + pBuffer += status; + size -= status; + } + break; + case ChunkStateFooter: + { + char _dummy[2]; + assert(encodingContext->nextOffset == 0); + assert(encodingContext->headerFooterPos < 2); + status = BIO_read(bio, _dummy, 2 - encodingContext->headerFooterPos); + if (status >= 0) + { + encodingContext->headerFooterPos += status; + if (encodingContext->headerFooterPos == 2) + { + encodingContext->state = ChunkStateLenghHeader; + encodingContext->headerFooterPos = 0; + } + } + else + return (effectiveDataLen > 0 ? effectiveDataLen : status); + } + break; + case ChunkStateLenghHeader: + { + BOOL _haveNewLine = FALSE; + size_t tmp; + char* dst = &encodingContext->lenBuffer[encodingContext->headerFooterPos]; + assert(encodingContext->nextOffset == 0); + while (encodingContext->headerFooterPos < 10 && !_haveNewLine) + { + status = BIO_read(bio, dst, 1); + if (status >= 0) + { + if (*dst == '\n') + _haveNewLine = TRUE; + encodingContext->headerFooterPos += status; + dst += status; + } + else + return (effectiveDataLen > 0 ? effectiveDataLen : status); + } + + *dst = '\0'; + + /* strtoul is tricky, error are reported via errno, we also need + * to ensure the result does not overflow */ + errno = 0; + tmp = strtoul(encodingContext->lenBuffer, NULL, 16); + if ((errno != 0) || (tmp > SIZE_MAX)) + return -1; + encodingContext->nextOffset = tmp; + encodingContext->state = ChunkStateData; + + if (encodingContext->nextOffset == 0) + { /* end of stream */ + int fd = BIO_get_fd(bio, NULL); + if (fd >= 0) + closesocket((SOCKET)fd); + + WLog_WARN(TAG, "cunked encoding end of stream received"); + encodingContext->headerFooterPos = 0; + encodingContext->state = ChunkStateFooter; + } + } + break; + default: + /* invalid state */ + return -1; + } + } + return -1; +} + +static int rdg_socket_read(BIO* bio, BYTE* pBuffer, size_t size, + rdg_http_encoding_context* encodingContext) +{ + assert(encodingContext != NULL); + if (encodingContext->isWebsocketTransport) + { + return rdg_websocket_read(bio, pBuffer, size, &encodingContext->context.websocket); + } + switch (encodingContext->httpTransferEncoding) + { + case TransferEncodingIdentity: + return BIO_read(bio, pBuffer, size); + case TransferEncodingChunked: + return rdg_chuncked_read(bio, pBuffer, size, &encodingContext->context.chunked); + default: + return -1; + } + return -1; /* should not be reached */ +} + +static BOOL rdg_read_all(rdpTls* tls, BYTE* buffer, size_t size, + rdg_http_encoding_context* transferEncoding) +{ + size_t readCount = 0; BYTE* pBuffer = buffer; while (readCount < size) { - status = BIO_read(tls->bio, pBuffer, size - readCount); + int status = rdg_socket_read(tls->bio, pBuffer, size - readCount, transferEncoding); if (status <= 0) { if (!BIO_should_retry(tls->bio)) return FALSE; + Sleep(10); continue; } @@ -295,7 +912,7 @@ if (!s) return NULL; - if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s), header)) + if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s), header, &rdg->transferEncoding)) { Stream_Free(s, TRUE); return NULL; @@ -311,7 +928,8 @@ return NULL; } - if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s) + header, (int)packetLength - (int)header)) + if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s) + header, (int)packetLength - (int)header, + &rdg->transferEncoding)) { Stream_Free(s, TRUE); return NULL; @@ -357,6 +975,9 @@ UINT16 fieldsPresent = 0; WCHAR* PAACookie = NULL; int PAACookieLen = 0; + const UINT32 capabilities = HTTP_CAPABILITY_TYPE_QUAR_SOH | + HTTP_CAPABILITY_MESSAGING_CONSENT_SIGN | + HTTP_CAPABILITY_MESSAGING_SERVICE_MSG; if (rdg->extAuth == HTTP_EXTENDED_AUTH_PAA) { @@ -381,12 +1002,12 @@ return FALSE; } - Stream_Write_UINT16(s, PKT_TYPE_TUNNEL_CREATE); /* Type (2 bytes) */ - Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */ - Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */ - Stream_Write_UINT32(s, HTTP_CAPABILITY_TYPE_QUAR_SOH); /* CapabilityFlags (4 bytes) */ - Stream_Write_UINT16(s, fieldsPresent); /* FieldsPresent (2 bytes) */ - Stream_Write_UINT16(s, 0); /* Reserved (2 bytes), must be 0 */ + Stream_Write_UINT16(s, PKT_TYPE_TUNNEL_CREATE); /* Type (2 bytes) */ + Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */ + Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */ + Stream_Write_UINT32(s, capabilities); /* CapabilityFlags (4 bytes) */ + Stream_Write_UINT16(s, fieldsPresent); /* FieldsPresent (2 bytes) */ + Stream_Write_UINT16(s, 0); /* Reserved (2 bytes), must be 0 */ if (PAACookie) { @@ -515,7 +1136,7 @@ } static wStream* rdg_build_http_request(rdpRdg* rdg, const char* method, - const char* transferEncoding) + TRANSFER_ENCODING transferEncoding) { wStream* s = NULL; HttpRequest* request = NULL; @@ -539,10 +1160,7 @@ goto out; } - if (transferEncoding) - { http_request_set_transfer_encoding(request, transferEncoding); - } s = http_request_write(rdg->http, request); out: @@ -607,7 +1225,8 @@ return TRUE; } -static BOOL rdg_skip_seed_payload(rdpTls* tls, SSIZE_T lastResponseLength) +static BOOL rdg_skip_seed_payload(rdpTls* tls, SSIZE_T lastResponseLength, + rdg_http_encoding_context* transferEncoding) { BYTE seed_payload[10]; const size_t size = sizeof(seed_payload); @@ -619,7 +1238,7 @@ */ if (lastResponseLength < (SSIZE_T)size) { - if (!rdg_read_all(tls, seed_payload, size - lastResponseLength)) + if (!rdg_read_all(tls, seed_payload, size - lastResponseLength, transferEncoding)) { return FALSE; } @@ -669,6 +1288,74 @@ return rdg_send_tunnel_request(rdg); } +static BOOL rdg_process_tunnel_response_optional(rdpRdg* rdg, wStream* s, UINT16 fieldsPresent) +{ + if (fieldsPresent & HTTP_TUNNEL_RESPONSE_FIELD_TUNNEL_ID) + { + /* Seek over tunnelId (4 bytes) */ + if (!Stream_SafeSeek(s, 4)) + { + WLog_ERR(TAG, "[%s] Short packet %" PRIuz ", expected 4", __FUNCTION__, + Stream_GetRemainingLength(s)); + return FALSE; + } + } + + if (fieldsPresent & HTTP_TUNNEL_RESPONSE_FIELD_CAPS) + { + UINT32 caps; + if (Stream_GetRemainingLength(s) < 4) + { + WLog_ERR(TAG, "[%s] Short packet %" PRIuz ", expected 4", __FUNCTION__, + Stream_GetRemainingLength(s)); + return FALSE; + } + + Stream_Read_UINT32(s, caps); + WLog_DBG(TAG, "capabilities=%s", capabilities_enum_to_string(caps)); + } + + if (fieldsPresent & HTTP_TUNNEL_RESPONSE_FIELD_SOH_REQ) + { + /* Seek over nonce (20 bytes) */ + if (!Stream_SafeSeek(s, 20)) + { + WLog_ERR(TAG, "[%s] Short packet %" PRIuz ", expected 20", __FUNCTION__, + Stream_GetRemainingLength(s)); + return FALSE; + } + + /* Read serverCert */ + if (!rdg_read_http_unicode_string(s, NULL, NULL)) + { + WLog_ERR(TAG, "[%s] Failed to read string", __FUNCTION__); + return FALSE; + } + } + + if (fieldsPresent & HTTP_TUNNEL_RESPONSE_FIELD_CONSENT_MSG) + { + const WCHAR* msg; + UINT16 msgLenBytes; + rdpContext* context = rdg->context; + + assert(context); + assert(context->instance); + + /* Read message string and invoke callback */ + if (!rdg_read_http_unicode_string(s, &msg, &msgLenBytes)) + { + WLog_ERR(TAG, "[%s] Failed to read string", __FUNCTION__); + return FALSE; + } + + return IFCALLRESULT(TRUE, context->instance->PresentGatewayMessage, context->instance, + GATEWAY_MESSAGE_CONSENT, TRUE, TRUE, msgLenBytes, msg); + } + + return TRUE; +} + static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s) { UINT16 serverVersion, fieldsPresent; @@ -703,6 +1390,9 @@ return FALSE; } + if (!rdg_process_tunnel_response_optional(rdg, s, fieldsPresent)) + return FALSE; + return rdg_send_tunnel_authorization(rdg); } @@ -949,7 +1639,7 @@ } static BOOL rdg_send_http_request(rdpRdg* rdg, rdpTls* tls, const char* method, - const char* transferEncoding) + TRANSFER_ENCODING transferEncoding) { size_t sz; wStream* s = NULL; @@ -1056,6 +1746,8 @@ long statusCode; SSIZE_T bodyLength; long StatusCode; + TRANSFER_ENCODING encoding; + BOOL isWebsocket; if (!rdg_tls_connect(rdg, tls, peerAddress, timeout)) return FALSE; @@ -1065,7 +1757,7 @@ if (!rdg_ntlm_init(rdg, tls)) return FALSE; - if (!rdg_send_http_request(rdg, tls, method, NULL)) + if (!rdg_send_http_request(rdg, tls, method, TransferEncodingIdentity)) return FALSE; response = http_response_recv(tls, TRUE); @@ -1080,6 +1772,7 @@ case HTTP_STATUS_NOT_FOUND: { WLog_INFO(TAG, "RD Gateway does not support HTTP transport."); + http_context_enable_websocket_upgrade(rdg->http, FALSE); if (rpcFallback) *rpcFallback = TRUE; @@ -1100,7 +1793,7 @@ http_response_free(response); } - if (!rdg_send_http_request(rdg, tls, method, NULL)) + if (!rdg_send_http_request(rdg, tls, method, TransferEncodingIdentity)) return FALSE; ntlm_free(rdg->ntlm); @@ -1112,28 +1805,66 @@ statusCode = http_response_get_status_code(response); bodyLength = http_response_get_body_length(response); + encoding = http_response_get_transfer_encoding(response); + isWebsocket = http_response_is_websocket(rdg->http, response); http_response_free(response); WLog_DBG(TAG, "%s authorization result: %d", method, statusCode); switch (statusCode) { case HTTP_STATUS_OK: + /* old rdg endpoint without websocket support, don't request websocket for RDG_IN_DATA + */ + http_context_enable_websocket_upgrade(rdg->http, FALSE); break; case HTTP_STATUS_DENIED: freerdp_set_last_error_log(rdg->context, FREERDP_ERROR_CONNECT_ACCESS_DENIED); return FALSE; + case HTTP_STATUS_SWITCH_PROTOCOLS: + if (!isWebsocket) + { + /* + * webserver is broken, a fallback may be possible here + * but only if already tested with oppurtonistic upgrade + */ + if (http_context_is_websocket_upgrade_enabled(rdg->http)) + { + int fd = BIO_get_fd(tls->bio, NULL); + if (fd >= 0) + closesocket((SOCKET)fd); + http_context_enable_websocket_upgrade(rdg->http, FALSE); + return rdg_establish_data_connection(rdg, tls, method, peerAddress, timeout, + rpcFallback); + } + return FALSE; + } + rdg->transferEncoding.isWebsocketTransport = TRUE; + rdg->transferEncoding.context.websocket.state = WebsocketStateOpcodeAndFin; + rdg->transferEncoding.context.websocket.responseStreamBuffer = NULL; + + return TRUE; + break; default: return FALSE; } if (strcmp(method, "RDG_OUT_DATA") == 0) { - if (!rdg_skip_seed_payload(tls, bodyLength)) + if (encoding == TransferEncodingChunked) + { + rdg->transferEncoding.httpTransferEncoding = TransferEncodingChunked; + rdg->transferEncoding.context.chunked.nextOffset = 0; + rdg->transferEncoding.context.chunked.headerFooterPos = 0; + rdg->transferEncoding.context.chunked.state = ChunkStateLenghHeader; + } + if (!rdg_skip_seed_payload(tls, bodyLength, &rdg->transferEncoding)) + { return FALSE; + } } else { - if (!rdg_send_http_request(rdg, tls, method, "chunked")) + if (!rdg_send_http_request(rdg, tls, method, TransferEncodingChunked)) return FALSE; } @@ -1178,14 +1909,21 @@ if (status) { - /* Establish IN connection with the same peer/server as OUT connection, - * even when server hostname resolves to different IP addresses. - */ - BIO_get_socket(rdg->tlsOut->underlying, &outConnSocket); - peerAddress = freerdp_tcp_get_peer_address(outConnSocket); - status = rdg_establish_data_connection(rdg, rdg->tlsIn, "RDG_IN_DATA", peerAddress, timeout, - NULL); - free(peerAddress); + if (rdg->transferEncoding.isWebsocketTransport) + { + WLog_DBG(TAG, "Upgraded to websocket. RDG_IN_DATA not required"); + } + else + { + /* Establish IN connection with the same peer/server as OUT connection, + * even when server hostname resolves to different IP addresses. + */ + BIO_get_socket(rdg->tlsOut->underlying, &outConnSocket); + peerAddress = freerdp_tcp_get_peer_address(outConnSocket); + status = rdg_establish_data_connection(rdg, rdg->tlsIn, "RDG_IN_DATA", peerAddress, + timeout, NULL); + free(peerAddress); + } } if (!status) @@ -1202,10 +1940,97 @@ return TRUE; } -static int rdg_write_data_packet(rdpRdg* rdg, const BYTE* buf, int isize) +static int rdg_write_websocket_data_packet(rdpRdg* rdg, const BYTE* buf, int isize) +{ + size_t payloadSize; + size_t fullLen; + int status; + wStream* sWS; + + uint32_t maskingKey; + BYTE* maskingKeyByte1 = (BYTE*)&maskingKey; + BYTE* maskingKeyByte2 = maskingKeyByte1 + 1; + BYTE* maskingKeyByte3 = maskingKeyByte1 + 2; + BYTE* maskingKeyByte4 = maskingKeyByte1 + 3; + + int streamPos; + + winpr_RAND((BYTE*)&maskingKey, 4); + + payloadSize = isize + 10; + if ((isize < 0) || (isize > UINT16_MAX)) + return -1; + + if (payloadSize < 1) + return 0; + + if (payloadSize < 126) + fullLen = payloadSize + 6; /* 2 byte "mini header" + 4 byte masking key */ + else if (payloadSize < 0x10000) + fullLen = payloadSize + 8; /* 2 byte "mini header" + 2 byte length + 4 byte masking key */ + else + fullLen = payloadSize + 14; /* 2 byte "mini header" + 8 byte length + 4 byte masking key */ + + sWS = Stream_New(NULL, fullLen); + if (!sWS) + return FALSE; + + Stream_Write_UINT8(sWS, WEBSOCKET_FIN_BIT | WebsocketBinaryOpcode); + if (payloadSize < 126) + Stream_Write_UINT8(sWS, payloadSize | WEBSOCKET_MASK_BIT); + else if (payloadSize < 0x10000) + { + Stream_Write_UINT8(sWS, 126 | WEBSOCKET_MASK_BIT); + Stream_Write_UINT16_BE(sWS, payloadSize); + } + else + { + Stream_Write_UINT8(sWS, 127 | WEBSOCKET_MASK_BIT); + /* biggest packet possible is 0xffff + 0xa, so 32bit is always enough */ + Stream_Write_UINT32_BE(sWS, 0); + Stream_Write_UINT32_BE(sWS, payloadSize); + } + Stream_Write_UINT32(sWS, maskingKey); + + Stream_Write_UINT16(sWS, PKT_TYPE_DATA ^ (*maskingKeyByte1 | *maskingKeyByte2 << 8)); /* Type */ + Stream_Write_UINT16(sWS, 0 ^ (*maskingKeyByte3 | *maskingKeyByte4 << 8)); /* Reserved */ + Stream_Write_UINT32(sWS, (UINT32)payloadSize ^ maskingKey); /* Packet length */ + Stream_Write_UINT16(sWS, + (UINT16)isize ^ (*maskingKeyByte1 | *maskingKeyByte2 << 8)); /* Data size */ + + /* masking key is now off by 2 bytes. fix that */ + maskingKey = (maskingKey & 0xffff) << 16 | (maskingKey >> 16); + + /* mask as much as possible with 32bit access */ + for (streamPos = 0; streamPos + 4 <= isize; streamPos += 4) + { + uint32_t masked = *((uint32_t*)((BYTE*)buf + streamPos)) ^ maskingKey; + Stream_Write_UINT32(sWS, masked); + } + + /* mask the rest byte by byte */ + for (; streamPos < isize; streamPos++) + { + BYTE* partialMask = (BYTE*)(&maskingKey) + streamPos % 4; + BYTE masked = *((BYTE*)((BYTE*)buf + streamPos)) ^ *partialMask; + Stream_Write_UINT8(sWS, masked); + } + + Stream_SealLength(sWS); + + status = tls_write_all(rdg->tlsOut, Stream_Buffer(sWS), Stream_Length(sWS)); + Stream_Free(sWS, TRUE); + + if (status < 0) + return status; + + return isize; +} + +static int rdg_write_chunked_data_packet(rdpRdg* rdg, const BYTE* buf, int isize) { int status; - size_t s; + size_t len; wStream* sChunk; size_t size = (size_t)isize; size_t packetSize = size + 10; @@ -1231,12 +2056,12 @@ Stream_Write(sChunk, buf, size); /* Data */ Stream_Write(sChunk, "\r\n", 2); Stream_SealLength(sChunk); - s = Stream_Length(sChunk); + len = Stream_Length(sChunk); - if (s > INT_MAX) + if (len > INT_MAX) return -1; - status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), (int)s); + status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), (int)len); Stream_Free(sChunk, TRUE); if (status < 0) @@ -1245,69 +2070,88 @@ return (int)size; } -static BOOL rdg_process_close_packet(rdpRdg* rdg) +static int rdg_write_data_packet(rdpRdg* rdg, const BYTE* buf, int isize) +{ + if (rdg->transferEncoding.isWebsocketTransport) + { + if (rdg->transferEncoding.context.websocket.closeSent == TRUE) + return -1; + return rdg_write_websocket_data_packet(rdg, buf, isize); + } + else + return rdg_write_chunked_data_packet(rdg, buf, isize); + + return -1; +} + +static BOOL rdg_process_close_packet(rdpRdg* rdg, wStream* s) { int status = -1; - size_t s; - wStream* sChunk; + wStream* sClose; + UINT32 errorCode; UINT32 packetSize = 12; - char chunkSize[11]; - int chunkLen = sprintf_s(chunkSize, sizeof(chunkSize), "%" PRIx32 "\r\n", packetSize); - if (chunkLen < 0) + /* Read error code */ + if (Stream_GetRemainingLength(s) < 4) return FALSE; + Stream_Read_UINT32(s, errorCode); - sChunk = Stream_New(NULL, (size_t)chunkLen + packetSize + 2); + if (errorCode != 0) + freerdp_set_last_error_log(rdg->context, errorCode); - if (!sChunk) + sClose = Stream_New(NULL, packetSize); + if (!sClose) return FALSE; - Stream_Write(sChunk, chunkSize, (size_t)chunkLen); - Stream_Write_UINT16(sChunk, PKT_TYPE_CLOSE_CHANNEL_RESPONSE); /* Type */ - Stream_Write_UINT16(sChunk, 0); /* Reserved */ - Stream_Write_UINT32(sChunk, packetSize); /* Packet length */ - Stream_Write_UINT32(sChunk, 0); /* Status code */ - Stream_Write(sChunk, "\r\n", 2); - Stream_SealLength(sChunk); - s = Stream_Length(sChunk); - - if (s <= INT_MAX) - status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), (int)s); + Stream_Write_UINT16(sClose, PKT_TYPE_CLOSE_CHANNEL_RESPONSE); /* Type */ + Stream_Write_UINT16(sClose, 0); /* Reserved */ + Stream_Write_UINT32(sClose, packetSize); /* Packet length */ + Stream_Write_UINT32(sClose, 0); /* Status code */ + Stream_SealLength(sClose); + status = rdg_write_packet(rdg, sClose); + Stream_Free(sClose, TRUE); - Stream_Free(sChunk, TRUE); return (status < 0 ? FALSE : TRUE); } static BOOL rdg_process_keep_alive_packet(rdpRdg* rdg) { int status = -1; - size_t s; - wStream* sChunk; + wStream* sKeepAlive; size_t packetSize = 8; - char chunkSize[11]; - int chunkLen = sprintf_s(chunkSize, sizeof(chunkSize), "%" PRIxz "\r\n", packetSize); - if ((chunkLen < 0) || (packetSize > UINT32_MAX)) + sKeepAlive = Stream_New(NULL, packetSize); + + if (!sKeepAlive) return FALSE; - sChunk = Stream_New(NULL, (size_t)chunkLen + packetSize + 2); + Stream_Write_UINT16(sKeepAlive, PKT_TYPE_KEEPALIVE); /* Type */ + Stream_Write_UINT16(sKeepAlive, 0); /* Reserved */ + Stream_Write_UINT32(sKeepAlive, (UINT32)packetSize); /* Packet length */ + Stream_SealLength(sKeepAlive); + status = rdg_write_packet(rdg, sKeepAlive); + Stream_Free(sKeepAlive, TRUE); - if (!sChunk) - return FALSE; + return (status < 0 ? FALSE : TRUE); +} - Stream_Write(sChunk, chunkSize, (size_t)chunkLen); - Stream_Write_UINT16(sChunk, PKT_TYPE_KEEPALIVE); /* Type */ - Stream_Write_UINT16(sChunk, 0); /* Reserved */ - Stream_Write_UINT32(sChunk, (UINT32)packetSize); /* Packet length */ - Stream_Write(sChunk, "\r\n", 2); - Stream_SealLength(sChunk); - s = Stream_Length(sChunk); +static BOOL rdg_process_service_message(rdpRdg* rdg, wStream* s) +{ + const WCHAR* msg; + UINT16 msgLenBytes; + rdpContext* context = rdg->context; + assert(context); + assert(context->instance); - if (s <= INT_MAX) - status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), (int)s); + /* Read message string */ + if (!rdg_read_http_unicode_string(s, &msg, &msgLenBytes)) + { + WLog_ERR(TAG, "[%s] Failed to read string", __FUNCTION__); + return FALSE; + } - Stream_Free(sChunk, TRUE); - return (status < 0 ? FALSE : TRUE); + return IFCALLRESULT(TRUE, context->instance->PresentGatewayMessage, context->instance, + GATEWAY_MESSAGE_SERVICE, TRUE, FALSE, msgLenBytes, msg); } static BOOL rdg_process_unknown_packet(rdpRdg* rdg, int type) @@ -1339,8 +2183,8 @@ while (readCount < payloadSize) { - status = - BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), (int)payloadSize - (int)readCount); + status = rdg_socket_read(rdg->tlsOut->bio, Stream_Pointer(s), payloadSize - readCount, + &rdg->transferEncoding); if (status <= 0) { @@ -1362,13 +2206,15 @@ return FALSE; } } + + Stream_SetPosition(s, 0); } switch (type) { case PKT_TYPE_CLOSE_CHANNEL: EnterCriticalSection(&rdg->writeSection); - status = rdg_process_close_packet(rdg); + status = rdg_process_close_packet(rdg, s); LeaveCriticalSection(&rdg->writeSection); break; @@ -1378,6 +2224,16 @@ LeaveCriticalSection(&rdg->writeSection); break; + case PKT_TYPE_SERVICE_MESSAGE: + if (!s) + { + WLog_ERR(TAG, "[%s] PKT_TYPE_SERVICE_MESSAGE requires payload but none was sent", + __FUNCTION__); + return FALSE; + } + status = rdg_process_service_message(rdg, s); + break; + default: status = rdg_process_unknown_packet(rdg, type); break; @@ -1391,7 +2247,7 @@ { RdgPacketHeader header; size_t readCount = 0; - int readSize; + size_t readSize; int status; if (!rdg->packetRemainingCount) @@ -1400,8 +2256,9 @@ while (readCount < sizeof(RdgPacketHeader)) { - status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&header) + readCount, - (int)sizeof(RdgPacketHeader) - (int)readCount); + status = rdg_socket_read(rdg->tlsOut->bio, (BYTE*)(&header) + readCount, + (int)sizeof(RdgPacketHeader) - (int)readCount, + &rdg->transferEncoding); if (status <= 0) { @@ -1435,8 +2292,9 @@ while (readCount < 2) { - status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&rdg->packetRemainingCount) + readCount, - 2 - (int)readCount); + status = + rdg_socket_read(rdg->tlsOut->bio, (BYTE*)(&rdg->packetRemainingCount) + readCount, + 2 - (int)readCount, &rdg->transferEncoding); if (status < 0) { @@ -1451,8 +2309,8 @@ } } - readSize = (rdg->packetRemainingCount < size ? rdg->packetRemainingCount : size); - status = BIO_read(rdg->tlsOut->bio, buffer, readSize); + readSize = (rdg->packetRemainingCount < size) ? rdg->packetRemainingCount : size; + status = rdg_socket_read(rdg->tlsOut->bio, buffer, readSize, &rdg->transferEncoding); if (status <= 0) { @@ -1688,7 +2546,8 @@ !http_context_set_connection(rdg->http, "Keep-Alive") || !http_context_set_user_agent(rdg->http, "MS-RDGateway/1.0") || !http_context_set_host(rdg->http, rdg->settings->GatewayHostname) || - !http_context_set_rdg_connection_id(rdg->http, bracedUuid)) + !http_context_set_rdg_connection_id(rdg->http, bracedUuid) || + !http_context_enable_websocket_upgrade(rdg->http, TRUE)) { goto rdg_alloc_error; } @@ -1716,6 +2575,9 @@ BIO_set_data(rdg->frontBio, rdg); InitializeCriticalSection(&rdg->writeSection); + + rdg->transferEncoding.httpTransferEncoding = TransferEncodingIdentity; + rdg->transferEncoding.isWebsocketTransport = FALSE; } return rdg; @@ -1738,6 +2600,12 @@ BIO_free_all(rdg->frontBio); DeleteCriticalSection(&rdg->writeSection); + if (rdg->transferEncoding.isWebsocketTransport) + { + if (rdg->transferEncoding.context.websocket.responseStreamBuffer != NULL) + Stream_Free(rdg->transferEncoding.context.websocket.responseStreamBuffer, TRUE); + } + free(rdg); } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc.c freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/rpc.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/rpc.c 2021-02-25 08:51:41.000000000 +0000 @@ -647,8 +647,8 @@ context = channel->client->context; settings = context->settings; - proxyUsername = settings->ProxyUsername; - proxyPassword = settings->ProxyPassword; + proxyUsername = freerdp_settings_get_string(settings, FreeRDP_ProxyUsername); + proxyPassword = freerdp_settings_get_string(settings, FreeRDP_ProxyPassword); { sockfd = freerdp_tcp_connect(context, settings, channel->client->host, channel->client->port, timeout); diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc_client.c freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/rpc_client.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc_client.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/rpc_client.c 2021-02-25 08:51:41.000000000 +0000 @@ -383,7 +383,8 @@ pdu->Type = PTYPE_RESPONSE; pdu->CallId = rpc->StubCallId; Stream_SealLength(pdu->s); - rpc_client_recv_pdu(rpc, pdu); + if (rpc_client_recv_pdu(rpc, pdu) < 0) + return -1; rpc_pdu_reset(pdu); rpc->StubFragCount = 0; rpc->StubCallId = 0; @@ -983,7 +984,7 @@ CopyMemory(&buffer[offset], &request_pdu.auth_verifier.auth_type, 8); offset += 8; Buffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY; /* auth_data */ - Buffers[1].BufferType = SECBUFFER_TOKEN; /* signature */ + Buffers[1].BufferType = SECBUFFER_TOKEN; /* signature */ Buffers[0].pvBuffer = buffer; Buffers[0].cbBuffer = offset; Buffers[1].cbBuffer = size; @@ -1022,10 +1023,10 @@ return FALSE; else { - const char* peerHostname = settings->GatewayHostname; - const char* proxyUsername = settings->ProxyUsername; - const char* proxyPassword = settings->ProxyPassword; - *port = settings->GatewayPort; + const char* peerHostname = freerdp_settings_get_string(settings, FreeRDP_GatewayHostname); + const char* proxyUsername = freerdp_settings_get_string(settings, FreeRDP_GatewayUsername); + const char* proxyPassword = freerdp_settings_get_string(settings, FreeRDP_GatewayPassword); + *port = freerdp_settings_get_uint32(settings, FreeRDP_GatewayPort); *isProxy = proxy_prepare(settings, &peerHostname, port, &proxyUsername, &proxyPassword); result = freerdp_tcp_resolve_host(peerHostname, *port, 0); @@ -1041,6 +1042,7 @@ RpcClient* rpc_client_new(rdpContext* context, UINT32 max_recv_frag) { + wObject* obj; RpcClient* client = (RpcClient*)calloc(1, sizeof(RpcClient)); if (!client) @@ -1081,7 +1083,11 @@ if (!client->ClientCallList) goto fail; - ArrayList_Object(client->ClientCallList)->fnObjectFree = rpc_array_client_call_free; + obj = ArrayList_Object(client->ClientCallList); + if (!obj) + goto fail; + + obj->fnObjectFree = rpc_array_client_call_free; return client; fail: rpc_client_free(client); diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc_fault.c freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/rpc_fault.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc_fault.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/rpc_fault.c 2021-02-25 08:51:41.000000000 +0000 @@ -30,201 +30,185 @@ #define TAG FREERDP_TAG("core.gateway.rpc") static const RPC_FAULT_CODE RPC_FAULT_CODES[] = { - DEFINE_RPC_FAULT_CODE(nca_s_fault_object_not_found, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - nca_s_fault_cancel, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(nca_s_fault_addr_error, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(nca_s_fault_context_mismatch, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - nca_s_fault_fp_div_zero, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(nca_s_fault_fp_error, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(nca_s_fault_fp_overflow, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - nca_s_fault_fp_underflow, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(nca_s_fault_ill_inst, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - nca_s_fault_int_div_by_zero, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(nca_s_fault_int_overflow, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - nca_s_fault_invalid_bound, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(nca_s_fault_invalid_tag, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_closed, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_comm_error, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_discipline, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_empty, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_memory, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_order, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(nca_s_fault_remote_no_memory, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(nca_s_fault_user_defined, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(nca_s_fault_tx_open_failed, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(nca_s_fault_codeset_conv_error, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(nca_s_fault_no_client_stub, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_STRING_BINDING, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_WRONG_KIND_OF_BINDING, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_BINDING, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_PROTSEQ_NOT_SUPPORTED, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_RPC_PROTSEQ, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_STRING_UUID, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_ENDPOINT_FORMAT, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NET_ADDR, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NO_ENDPOINT_FOUND, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_TIMEOUT, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_OBJECT_NOT_FOUND, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_ALREADY_REGISTERED, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_TYPE_ALREADY_REGISTERED, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_ALREADY_LISTENING, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NO_PROTSEQS_REGISTERED, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NOT_LISTENING, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_MGR_TYPE, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_IF, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NO_BINDINGS, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NO_PROTSEQS, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_CANT_CREATE_ENDPOINT, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_OUT_OF_RESOURCES, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_SERVER_UNAVAILABLE, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_SERVER_TOO_BUSY, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NETWORK_OPTIONS, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NO_CALL_ACTIVE, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_CALL_FAILED, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_CALL_FAILED_DNE, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_PROTOCOL_ERROR, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_PROXY_ACCESS_DENIED, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_UNSUPPORTED_TRANS_SYN, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_UNSUPPORTED_TYPE, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_TAG, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_BOUND, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NO_ENTRY_NAME, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NAME_SYNTAX, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_UNSUPPORTED_NAME_SYNTAX, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_UUID_NO_ADDRESS, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_DUPLICATE_ENDPOINT, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHN_TYPE, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_MAX_CALLS_TOO_SMALL, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_STRING_TOO_LONG, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_PROTSEQ_NOT_FOUND, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_PROCNUM_OUT_OF_RANGE, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_BINDING_HAS_NO_AUTH, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHN_SERVICE, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHN_LEVEL, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_AUTH_IDENTITY, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHZ_SERVICE, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(EPT_S_INVALID_ENTRY, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(EPT_S_CANT_PERFORM_OP, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(EPT_S_NOT_REGISTERED, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NOTHING_TO_EXPORT, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INCOMPLETE_NAME, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_VERS_OPTION, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NO_MORE_MEMBERS, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NOT_ALL_OBJS_UNEXPORTED, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INTERFACE_NOT_FOUND, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_ENTRY_ALREADY_EXISTS, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_ENTRY_NOT_FOUND, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NAME_SERVICE_UNAVAILABLE, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NAF_ID, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_CANNOT_SUPPORT, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NO_CONTEXT_AVAILABLE, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INTERNAL_ERROR, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_ZERO_DIVIDE, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_ADDRESS_ERROR, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_FP_DIV_ZERO, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_FP_UNDERFLOW, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_FP_OVERFLOW, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_NO_MORE_ENTRIES, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(RPC_X_SS_CHAR_TRANS_OPEN_FAIL, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_SS_CHAR_TRANS_SHORT_FILE, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - RPC_X_SS_IN_NULL_CONTEXT, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_SS_CONTEXT_DAMAGED, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_SS_HANDLES_MISMATCH, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(RPC_X_SS_CANNOT_GET_CALL_HANDLE, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_NULL_REF_POINTER, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - RPC_X_ENUM_VALUE_OUT_OF_RANGE, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_BYTE_COUNT_TOO_SMALL, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_BAD_STUB_DATA, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - RPC_S_NO_INTERFACES, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_CALL_CANCELLED, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_BINDING_INCOMPLETE, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(RPC_S_COMM_FAILURE, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - RPC_S_UNSUPPORTED_AUTHN_LEVEL, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_NO_PRINC_NAME, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(RPC_S_NOT_RPC_ERROR, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - RPC_S_UUID_LOCAL_ONLY, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_SEC_PKG_ERROR, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - RPC_S_NOT_CANCELLED, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_ES_ACTION, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - RPC_X_WRONG_ES_VERSION, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_WRONG_STUB_VERSION, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - RPC_X_INVALID_PIPE_OBJECT, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - RPC_X_WRONG_PIPE_ORDER, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - RPC_X_WRONG_PIPE_VERSION, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - RPC_S_COOKIE_AUTH_FAILED, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - RPC_S_GROUP_MEMBER_NOT_FOUND, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - EPT_S_CANT_CREATE, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - RPC_S_INVALID_OBJECT, - CAT_GATEWAY){ - 0, - NULL, - NULL } + DEFINE_RPC_FAULT_CODE(nca_s_fault_object_not_found, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_cancel, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_addr_error, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_context_mismatch, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_fp_div_zero, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_fp_error, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_fp_overflow, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_fp_underflow, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_ill_inst, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_int_div_by_zero, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_int_overflow, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_invalid_bound, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_invalid_tag, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_closed, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_comm_error, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_discipline, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_empty, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_memory, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_pipe_order, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_remote_no_memory, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_user_defined, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_tx_open_failed, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_codeset_conv_error, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(nca_s_fault_no_client_stub, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_STRING_BINDING, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_WRONG_KIND_OF_BINDING, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_BINDING, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_PROTSEQ_NOT_SUPPORTED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_RPC_PROTSEQ, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_STRING_UUID, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_ENDPOINT_FORMAT, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NET_ADDR, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NO_ENDPOINT_FOUND, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_TIMEOUT, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_OBJECT_NOT_FOUND, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_ALREADY_REGISTERED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_TYPE_ALREADY_REGISTERED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_ALREADY_LISTENING, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NO_PROTSEQS_REGISTERED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NOT_LISTENING, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_MGR_TYPE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_IF, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NO_BINDINGS, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NO_PROTSEQS, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_CANT_CREATE_ENDPOINT, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_OUT_OF_RESOURCES, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_SERVER_UNAVAILABLE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_SERVER_TOO_BUSY, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NETWORK_OPTIONS, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NO_CALL_ACTIVE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_CALL_FAILED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_CALL_FAILED_DNE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_PROTOCOL_ERROR, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_PROXY_ACCESS_DENIED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UNSUPPORTED_TRANS_SYN, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UNSUPPORTED_TYPE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_TAG, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_BOUND, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NO_ENTRY_NAME, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NAME_SYNTAX, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UNSUPPORTED_NAME_SYNTAX, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UUID_NO_ADDRESS, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_DUPLICATE_ENDPOINT, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHN_TYPE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_MAX_CALLS_TOO_SMALL, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_STRING_TOO_LONG, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_PROTSEQ_NOT_FOUND, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_PROCNUM_OUT_OF_RANGE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_BINDING_HAS_NO_AUTH, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHN_SERVICE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHN_LEVEL, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_AUTH_IDENTITY, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_AUTHZ_SERVICE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(EPT_S_INVALID_ENTRY, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(EPT_S_CANT_PERFORM_OP, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(EPT_S_NOT_REGISTERED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NOTHING_TO_EXPORT, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INCOMPLETE_NAME, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_VERS_OPTION, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NO_MORE_MEMBERS, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NOT_ALL_OBJS_UNEXPORTED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INTERFACE_NOT_FOUND, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_ENTRY_ALREADY_EXISTS, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_ENTRY_NOT_FOUND, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NAME_SERVICE_UNAVAILABLE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_NAF_ID, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_CANNOT_SUPPORT, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NO_CONTEXT_AVAILABLE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INTERNAL_ERROR, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_ZERO_DIVIDE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_ADDRESS_ERROR, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_FP_DIV_ZERO, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_FP_UNDERFLOW, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_FP_OVERFLOW, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_NO_MORE_ENTRIES, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_SS_CHAR_TRANS_OPEN_FAIL, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_SS_CHAR_TRANS_SHORT_FILE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_SS_IN_NULL_CONTEXT, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_SS_CONTEXT_DAMAGED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_SS_HANDLES_MISMATCH, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_SS_CANNOT_GET_CALL_HANDLE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_NULL_REF_POINTER, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_ENUM_VALUE_OUT_OF_RANGE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_BYTE_COUNT_TOO_SMALL, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_BAD_STUB_DATA, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NO_INTERFACES, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_CALL_CANCELLED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_BINDING_INCOMPLETE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_COMM_FAILURE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UNSUPPORTED_AUTHN_LEVEL, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NO_PRINC_NAME, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NOT_RPC_ERROR, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UUID_LOCAL_ONLY, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_SEC_PKG_ERROR, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_NOT_CANCELLED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_ES_ACTION, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_WRONG_ES_VERSION, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_WRONG_STUB_VERSION, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_PIPE_OBJECT, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_WRONG_PIPE_ORDER, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_WRONG_PIPE_VERSION, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_COOKIE_AUTH_FAILED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_GROUP_MEMBER_NOT_FOUND, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(EPT_S_CANT_CREATE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_OBJECT, CAT_GATEWAY), + { 0, NULL, NULL } }; static const RPC_FAULT_CODE RPC_TSG_FAULT_CODES[] = { - DEFINE_RPC_FAULT_CODE(RPC_S_OK, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - RPC_S_INVALID_ARG, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_OUT_OF_MEMORY, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_OUT_OF_THREADS, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_LEVEL, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - RPC_S_BUFFER_TOO_SMALL, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_SECURITY_DESC, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_ACCESS_DENIED, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(RPC_S_SERVER_OUT_OF_MEMORY, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - RPC_S_ASYNC_CALL_PENDING, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_PRINCIPAL, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_S_TIMEOUT, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(RPC_X_NO_MEMORY, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - RPC_X_INVALID_BOUND, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_TAG, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_ENUM_VALUE_TOO_LARGE, - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(RPC_X_SS_CONTEXT_MISMATCH, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - RPC_X_INVALID_BUFFER, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(RPC_X_PIPE_APP_MEMORY, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_PIPE_OPERATION, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - ERROR_ONLY_IF_CONNECTED, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(ERROR_GRACEFUL_DISCONNECT, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(ERROR_OPERATION_ABORTED, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - ERROR_BAD_ARGUMENTS, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(E_PROXY_INTERNALERROR, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(E_PROXY_RAP_ACCESSDENIED, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - E_PROXY_NAP_ACCESSDENIED, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(E_PROXY_TS_CONNECTFAILED, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(E_PROXY_ALREADYDISCONNECTED, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - E_PROXY_QUARANTINE_ACCESSDENIED, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(E_PROXY_NOCERTAVAILABLE, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(E_PROXY_COOKIE_BADPACKET, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - E_PROXY_COOKIE_AUTHENTICATION_ACCESS_DENIED, - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(E_PROXY_UNSUPPORTED_AUTHENTICATION_METHOD, CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE(E_PROXY_CAPABILITYMISMATCH, CAT_GATEWAY) DEFINE_RPC_FAULT_CODE( - HRESULT_CODE(E_PROXY_NOTSUPPORTED), - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE(E_PROXY_TS_CONNECTFAILED), - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE(E_PROXY_MAXCONNECTIONSREACHED), - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE(E_PROXY_INTERNALERROR), - CAT_GATEWAY) DEFINE_RPC_FAULT_CODE(HRESULT_CODE(E_PROXY_SESSIONTIMEOUT), - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE( - E_PROXY_REAUTH_AUTHN_FAILED), - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE( - E_PROXY_REAUTH_CAP_FAILED), - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE( - E_PROXY_REAUTH_RAP_FAILED), - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE( - E_PROXY_SDR_NOT_SUPPORTED_BY_TS), - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE( - E_PROXY_REAUTH_NAP_FAILED), - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE( - E_PROXY_CONNECTIONABORTED), - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE( - E_PROXY_NOCERTAVAILABLE), - CAT_GATEWAY) - DEFINE_RPC_FAULT_CODE( - HRESULT_CODE( - RPC_S_CALL_CANCELLED), - CAT_GATEWAY){ - 0, NULL, - NULL } + DEFINE_RPC_FAULT_CODE(RPC_S_OK, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_ARG, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_OUT_OF_MEMORY, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_OUT_OF_THREADS, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_LEVEL, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_BUFFER_TOO_SMALL, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_INVALID_SECURITY_DESC, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_ACCESS_DENIED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_SERVER_OUT_OF_MEMORY, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_ASYNC_CALL_PENDING, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_UNKNOWN_PRINCIPAL, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_S_TIMEOUT, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_NO_MEMORY, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_BOUND, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_TAG, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_ENUM_VALUE_TOO_LARGE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_SS_CONTEXT_MISMATCH, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_BUFFER, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_PIPE_APP_MEMORY, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(RPC_X_INVALID_PIPE_OPERATION, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(ERROR_ONLY_IF_CONNECTED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(ERROR_GRACEFUL_DISCONNECT, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(ERROR_OPERATION_ABORTED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(ERROR_BAD_ARGUMENTS, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(E_PROXY_INTERNALERROR, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(E_PROXY_RAP_ACCESSDENIED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(E_PROXY_NAP_ACCESSDENIED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(E_PROXY_TS_CONNECTFAILED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(E_PROXY_ALREADYDISCONNECTED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(E_PROXY_QUARANTINE_ACCESSDENIED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(E_PROXY_NOCERTAVAILABLE, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(E_PROXY_COOKIE_BADPACKET, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(E_PROXY_COOKIE_AUTHENTICATION_ACCESS_DENIED, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(E_PROXY_UNSUPPORTED_AUTHENTICATION_METHOD, CAT_GATEWAY), + DEFINE_RPC_FAULT_CODE(E_PROXY_CAPABILITYMISMATCH, CAT_GATEWAY), + { HRESULT_CODE(E_PROXY_NOTSUPPORTED), "E_PROXY_NOTSUPPORTED", CAT_GATEWAY }, + { HRESULT_CODE(E_PROXY_TS_CONNECTFAILED), "E_PROXY_TS_CONNECTFAILED", CAT_GATEWAY }, + { HRESULT_CODE(E_PROXY_MAXCONNECTIONSREACHED), "E_PROXY_MAXCONNECTIONSREACHED", CAT_GATEWAY }, + { HRESULT_CODE(E_PROXY_INTERNALERROR), "E_PROXY_INTERNALERROR", CAT_GATEWAY }, + { HRESULT_CODE(E_PROXY_SESSIONTIMEOUT), "E_PROXY_SESSIONTIMEOUT", CAT_GATEWAY }, + { HRESULT_CODE(E_PROXY_REAUTH_AUTHN_FAILED), "E_PROXY_REAUTH_AUTHN_FAILED", CAT_GATEWAY }, + { HRESULT_CODE(E_PROXY_REAUTH_CAP_FAILED), "E_PROXY_REAUTH_CAP_FAILED", CAT_GATEWAY }, + { HRESULT_CODE(E_PROXY_REAUTH_RAP_FAILED), "E_PROXY_REAUTH_RAP_FAILED", CAT_GATEWAY }, + { HRESULT_CODE(E_PROXY_SDR_NOT_SUPPORTED_BY_TS), "E_PROXY_SDR_NOT_SUPPORTED_BY_TS", + CAT_GATEWAY }, + { HRESULT_CODE(E_PROXY_REAUTH_NAP_FAILED), "E_PROXY_REAUTH_NAP_FAILED", CAT_GATEWAY }, + { HRESULT_CODE(E_PROXY_CONNECTIONABORTED), "E_PROXY_CONNECTIONABORTED", CAT_GATEWAY }, + { HRESULT_CODE(E_PROXY_NOCERTAVAILABLE), "E_PROXY_NOCERTAVAILABLE", CAT_GATEWAY }, + { HRESULT_CODE(RPC_S_CALL_CANCELLED), "RPC_S_CALL_CANCELLED", CAT_GATEWAY }, + { 0, NULL, NULL } }; /** @@ -381,8 +365,7 @@ { if (RPC_FAULT_CODES[index].code == code) { - sprintf_s(buffer, ARRAYSIZE(buffer), "%s [0x%08" PRIX32 "]", - RPC_FAULT_CODES[index].name, code); + sprintf_s(buffer, ARRAYSIZE(buffer), "%s", RPC_FAULT_CODES[index].name); goto out; } } @@ -391,8 +374,16 @@ { if (RPC_TSG_FAULT_CODES[index].code == code) { - sprintf_s(buffer, ARRAYSIZE(buffer), "%s [0x%08" PRIX32 "]", - RPC_TSG_FAULT_CODES[index].name, code); + sprintf_s(buffer, ARRAYSIZE(buffer), "%s", RPC_TSG_FAULT_CODES[index].name); + goto out; + } + } + + for (index = 0; RPC_TSG_FAULT_CODES[index].name != NULL; index++) + { + if (RPC_TSG_FAULT_CODES[index].code == HRESULT_CODE(code)) + { + sprintf_s(buffer, ARRAYSIZE(buffer), "%s", RPC_TSG_FAULT_CODES[index].name); goto out; } } @@ -418,6 +409,12 @@ return RPC_TSG_FAULT_CODES[index].category; } + for (index = 0; RPC_TSG_FAULT_CODES[index].category != NULL; index++) + { + if (RPC_TSG_FAULT_CODES[index].code == HRESULT_CODE(code)) + return RPC_TSG_FAULT_CODES[index].category; + } + return "UNKNOWN"; } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc.h freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/rpc.h --- freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/rpc.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/rpc.h 2021-02-25 08:51:41.000000000 +0000 @@ -407,7 +407,10 @@ }; typedef struct _RPC_FAULT_CODE RPC_FAULT_CODE; -#define DEFINE_RPC_FAULT_CODE(_code, cat) { _code, #_code, cat }, +#define DEFINE_RPC_FAULT_CODE(_code, cat) \ + { \ + _code, #_code, cat \ + } #define nca_s_comm_failure 0x1C010001 #define nca_s_op_rng_error 0x1C010002 diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/tsg.c freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/tsg.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/gateway/tsg.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/gateway/tsg.c 2021-02-25 08:51:41.000000000 +0000 @@ -74,7 +74,8 @@ UINT32 capabilities; } TSG_CAPABILITY_NAP, *PTSG_CAPABILITY_NAP; -typedef union { +typedef union +{ TSG_CAPABILITY_NAP tsgCapNap; } TSG_CAPABILITIES_UNION, *PTSG_CAPABILITIES_UNION; @@ -176,7 +177,8 @@ BYTE* cookie; } TSG_PACKET_AUTH, *PTSG_PACKET_AUTH; -typedef union { +typedef union +{ PTSG_PACKET_VERSIONCAPS packetVersionCaps; PTSG_PACKET_AUTH packetAuth; } TSG_INITIAL_PACKET_TYPE_UNION, *PTSG_INITIAL_PACKET_TYPE_UNION; @@ -188,7 +190,8 @@ TSG_INITIAL_PACKET_TYPE_UNION tsgInitialPacket; } TSG_PACKET_REAUTH, *PTSG_PACKET_REAUTH; -typedef union { +typedef union +{ PTSG_PACKET_HEADER packetHeader; PTSG_PACKET_VERSIONCAPS packetVersionCaps; PTSG_PACKET_QUARCONFIGREQUEST packetQuarConfigRequest; @@ -722,9 +725,9 @@ UINT32 SwitchValue; UINT32 MessageSwitchValue = 0; UINT32 IsMessagePresent; - UINT32 MsgBytes; PTSG_PACKET_CAPABILITIES tsgCaps = NULL; PTSG_PACKET_VERSIONCAPS versionCaps = NULL; + TSG_PACKET_STRING_MESSAGE packetStringMessage; PTSG_PACKET_CAPS_RESPONSE packetCapsResponse = NULL; PTSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse = NULL; @@ -874,9 +877,9 @@ if (Stream_GetRemainingLength(pdu->s) < 16) goto fail; - Stream_Seek_UINT32(pdu->s); /* IsDisplayMandatory (4 bytes) */ - Stream_Seek_UINT32(pdu->s); /* IsConsent Mandatory (4 bytes) */ - Stream_Read_UINT32(pdu->s, MsgBytes); + Stream_Read_UINT32(pdu->s, packetStringMessage.isDisplayMandatory); + Stream_Read_UINT32(pdu->s, packetStringMessage.isConsentMandatory); + Stream_Read_UINT32(pdu->s, packetStringMessage.msgBytes); Stream_Read_UINT32(pdu->s, Pointer); if (Pointer) @@ -889,15 +892,36 @@ Stream_Seek_UINT32(pdu->s); /* Length (4 bytes) */ } - if (MsgBytes > TSG_MESSAGING_MAX_MESSAGE_LENGTH) + if (packetStringMessage.msgBytes > TSG_MESSAGING_MAX_MESSAGE_LENGTH) { - WLog_ERR(TAG, "Out of Spec Message Length %" PRIu32 "", MsgBytes); + WLog_ERR(TAG, "Out of Spec Message Length %" PRIu32 "", + packetStringMessage.msgBytes); goto fail; } - if (!Stream_SafeSeek(pdu->s, MsgBytes)) + packetStringMessage.msgBuffer = (WCHAR*)Stream_Pointer(pdu->s); + if (Stream_GetRemainingLength(pdu->s) < packetStringMessage.msgBytes) + { + WLog_ERR(TAG, "Unable to read message (%" PRIu32 " remaining %" PRId32 ")", + packetStringMessage.msgBytes, Stream_GetRemainingLength(pdu->s)); goto fail; + } + + if (tsg->rpc && tsg->rpc->context && tsg->rpc->context->instance) + { + rc = IFCALLRESULT(TRUE, tsg->rpc->context->instance->PresentGatewayMessage, + tsg->rpc->context->instance, + TSG_ASYNC_MESSAGE_CONSENT_MESSAGE + ? GATEWAY_MESSAGE_CONSENT + : TSG_ASYNC_MESSAGE_SERVICE_MESSAGE, + packetStringMessage.isDisplayMandatory != 0, + packetStringMessage.isConsentMandatory != 0, + packetStringMessage.msgBytes, packetStringMessage.msgBuffer); + if (!rc) + goto fail; + } + Stream_Seek(pdu->s, packetStringMessage.msgBytes); break; case TSG_ASYNC_MESSAGE_REAUTH: @@ -1335,7 +1359,7 @@ if (tsg->rpc && tsg->rpc->context && tsg->rpc->context->instance) { rc = IFCALLRESULT(TRUE, tsg->rpc->context->instance->PresentGatewayMessage, - tsg->rpc->context->instance, SwitchValue, + tsg->rpc->context->instance, GATEWAY_MESSAGE_CONSENT, packetStringMessage.isDisplayMandatory != 0, packetStringMessage.isConsentMandatory != 0, packetStringMessage.msgBytes, packetStringMessage.msgBuffer); @@ -1356,7 +1380,7 @@ if (tsg->rpc && tsg->rpc->context && tsg->rpc->context->instance) { rc = IFCALLRESULT(TRUE, tsg->rpc->context->instance->PresentGatewayMessage, - tsg->rpc->context->instance, SwitchValue, + tsg->rpc->context->instance, GATEWAY_MESSAGE_SERVICE, packetStringMessage.isDisplayMandatory != 0, packetStringMessage.isConsentMandatory != 0, packetStringMessage.msgBytes, packetStringMessage.msgBuffer); diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/gcc.c freerdp2-2.3.0+dfsg1/libfreerdp/core/gcc.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/gcc.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/gcc.c 2021-02-25 08:51:41.000000000 +0000 @@ -53,9 +53,9 @@ static BOOL gcc_write_server_network_data(wStream* s, rdpMcs* mcs); static void gcc_write_client_cluster_data(wStream* s, rdpMcs* mcs); static BOOL gcc_read_client_monitor_data(wStream* s, rdpMcs* mcs, UINT16 blockLength); -static void gcc_write_client_monitor_data(wStream* s, rdpMcs* mcs); +static BOOL gcc_write_client_monitor_data(wStream* s, rdpMcs* mcs); static BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpMcs* mcs, UINT16 blockLength); -static void gcc_write_client_monitor_extended_data(wStream* s, rdpMcs* mcs); +static BOOL gcc_write_client_monitor_extended_data(wStream* s, rdpMcs* mcs); static BOOL gcc_read_client_message_channel_data(wStream* s, rdpMcs* mcs, UINT16 blockLength); static void gcc_write_client_message_channel_data(wStream* s, rdpMcs* mcs); static BOOL gcc_read_server_message_channel_data(wStream* s, rdpMcs* mcs); @@ -469,7 +469,7 @@ return TRUE; } -void gcc_write_client_data_blocks(wStream* s, rdpMcs* mcs) +BOOL gcc_write_client_data_blocks(wStream* s, rdpMcs* mcs) { rdpSettings* settings = mcs->settings; gcc_write_client_core_data(s, mcs); @@ -483,8 +483,11 @@ { if (settings->UseMultimon && !settings->SpanMonitors) { - gcc_write_client_monitor_data(s, mcs); - gcc_write_client_monitor_extended_data(s, mcs); + if (!gcc_write_client_monitor_data(s, mcs)) + return FALSE; + + if (!gcc_write_client_monitor_extended_data(s, mcs)) + return FALSE; } gcc_write_client_message_channel_data(s, mcs); @@ -499,8 +502,11 @@ if (settings->ForceMultimon) { WLog_ERR(TAG, "Sending multi monitor information anyway (may break connectivity!)"); - gcc_write_client_monitor_data(s, mcs); - gcc_write_client_monitor_extended_data(s, mcs); + if (!gcc_write_client_monitor_data(s, mcs)) + return FALSE; + + if (!gcc_write_client_monitor_extended_data(s, mcs)) + return FALSE; } else { @@ -508,6 +514,8 @@ } } } + + return TRUE; } BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length) @@ -871,7 +879,7 @@ if (settings->NetworkAutoDetect) settings->NetworkAutoDetect = - (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT) ? TRUE : FALSE; + (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT) ? TRUE : FALSE; if (settings->SupportHeartbeatPdu) settings->SupportHeartbeatPdu = @@ -954,12 +962,6 @@ supportedColorDepths = RNS_UD_24BPP_SUPPORT | RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT; earlyCapabilityFlags = RNS_UD_CS_SUPPORT_ERRINFO_PDU; - if (settings->NetworkAutoDetect) - settings->ConnectionType = CONNECTION_TYPE_AUTODETECT; - - if (settings->RemoteFxCodec && !settings->NetworkAutoDetect) - settings->ConnectionType = CONNECTION_TYPE_LAN; - connectionType = settings->ConnectionType; if (connectionType) @@ -972,7 +974,7 @@ } if (settings->NetworkAutoDetect) - earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_NETWORK_AUTODETECT; + earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT; if (settings->SupportHeartbeatPdu) earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_HEARTBEAT_PDU; @@ -1788,7 +1790,7 @@ * @param settings rdp settings */ -void gcc_write_client_monitor_data(wStream* s, rdpMcs* mcs) +BOOL gcc_write_client_monitor_data(wStream* s, rdpMcs* mcs) { UINT32 i; UINT16 length; @@ -1799,6 +1801,9 @@ if (settings->MonitorCount > 1) { length = (20 * settings->MonitorCount) + 12; + if (!Stream_EnsureRemainingCapacity(s, length)) + return FALSE; + gcc_write_user_data_header(s, CS_MONITOR, length); Stream_Write_UINT32(s, 0); /* flags */ Stream_Write_UINT32(s, settings->MonitorCount); /* monitorCount */ @@ -1829,6 +1834,8 @@ Stream_Write_UINT32(s, flags); /* flags */ } } + + return TRUE; } BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) @@ -1875,7 +1882,7 @@ return TRUE; } -void gcc_write_client_monitor_extended_data(wStream* s, rdpMcs* mcs) +BOOL gcc_write_client_monitor_extended_data(wStream* s, rdpMcs* mcs) { UINT32 i; UINT16 length; @@ -1884,6 +1891,9 @@ if (settings->HasMonitorAttributes) { length = (20 * settings->MonitorCount) + 16; + if (!Stream_EnsureRemainingCapacity(s, length)) + return FALSE; + gcc_write_user_data_header(s, CS_MONITOR_EX, length); Stream_Write_UINT32(s, 0); /* flags */ Stream_Write_UINT32(s, 20); /* monitorAttributeSize */ @@ -1904,6 +1914,8 @@ settings->MonitorDefArray[i].attributes.deviceScaleFactor); /* deviceScaleFactor */ } } + + return TRUE; } /** diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/gcc.h freerdp2-2.3.0+dfsg1/libfreerdp/core/gcc.h --- freerdp2-2.2.0+dfsg1/libfreerdp/core/gcc.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/gcc.h 2021-02-25 08:51:41.000000000 +0000 @@ -34,7 +34,7 @@ FREERDP_LOCAL void gcc_write_conference_create_request(wStream* s, wStream* userData); FREERDP_LOCAL BOOL gcc_read_conference_create_response(wStream* s, rdpMcs* mcs); FREERDP_LOCAL void gcc_write_conference_create_response(wStream* s, wStream* userData); -FREERDP_LOCAL void gcc_write_client_data_blocks(wStream* s, rdpMcs* mcs); +FREERDP_LOCAL BOOL gcc_write_client_data_blocks(wStream* s, rdpMcs* mcs); FREERDP_LOCAL BOOL gcc_write_server_data_blocks(wStream* s, rdpMcs* mcs); #endif /* FREERDP_LIB_CORE_GCC_H */ diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/info.c freerdp2-2.3.0+dfsg1/libfreerdp/core/info.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/info.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/info.c 2021-02-25 08:51:41.000000000 +0000 @@ -496,7 +496,7 @@ if (unicode) { - if (ConvertFromUnicode(CP_UTF8, 0, domain, cbLenNonNull, &ret, 0, NULL, NULL) < 1) + if (ConvertFromUnicode(CP_UTF8, 0, domain, -1, &ret, 0, NULL, NULL) < 1) { WLog_ERR(TAG, "failed to convert Domain string"); return FALSE; diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/mcs.c freerdp2-2.3.0+dfsg1/libfreerdp/core/mcs.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/mcs.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/mcs.c 2021-02-25 08:51:41.000000000 +0000 @@ -701,7 +701,9 @@ return FALSE; } - gcc_write_client_data_blocks(client_data, mcs); + if (!gcc_write_client_data_blocks(client_data, mcs)) + goto out; + gcc_CCrq = Stream_New(NULL, 1024); if (!gcc_CCrq) @@ -734,7 +736,8 @@ if (length > UINT16_MAX) goto out; Stream_SetPosition(s, bm); - tpkt_write_header(s, (UINT16)length); + if (!tpkt_write_header(s, (UINT16)length)) + goto out; tpdu_write_data(s); Stream_SetPosition(s, em); Stream_SealLength(s); @@ -796,11 +799,11 @@ BOOL mcs_send_connect_response(rdpMcs* mcs) { size_t length; - int status; - wStream* s; + int status = -1; + wStream* s = NULL; size_t bm, em; - wStream* gcc_CCrsp; - wStream* server_data; + wStream* gcc_CCrsp = NULL; + wStream* server_data = NULL; if (!mcs) return FALSE; @@ -814,14 +817,14 @@ } if (!gcc_write_server_data_blocks(server_data, mcs)) - goto error_data_blocks; + goto out; gcc_CCrsp = Stream_New(NULL, 512 + Stream_Capacity(server_data)); if (!gcc_CCrsp) { WLog_ERR(TAG, "Stream_New failed!"); - goto error_data_blocks; + goto out; } gcc_write_conference_create_response(gcc_CCrsp, server_data); @@ -831,36 +834,31 @@ if (!s) { WLog_ERR(TAG, "Stream_New failed!"); - goto error_stream_s; + goto out; } bm = Stream_GetPosition(s); Stream_Seek(s, 7); if (!mcs_write_connect_response(s, mcs, gcc_CCrsp)) - goto error_write_connect_response; + goto out; em = Stream_GetPosition(s); length = (em - bm); if (length > UINT16_MAX) - goto error_write_connect_response; + goto out; Stream_SetPosition(s, bm); - tpkt_write_header(s, (UINT16)length); + if (!tpkt_write_header(s, (UINT16)length)) + goto out; tpdu_write_data(s); Stream_SetPosition(s, em); Stream_SealLength(s); status = transport_write(mcs->transport, s); +out: Stream_Free(s, TRUE); Stream_Free(gcc_CCrsp, TRUE); Stream_Free(server_data, TRUE); return (status < 0) ? FALSE : TRUE; -error_write_connect_response: - Stream_Free(s, TRUE); -error_stream_s: - Stream_Free(gcc_CCrsp, TRUE); -error_data_blocks: - Stream_Free(server_data, TRUE); - return FALSE; } /** diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/message.c freerdp2-2.3.0+dfsg1/libfreerdp/core/message.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/message.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/message.c 2021-02-25 08:51:41.000000000 +0000 @@ -2804,6 +2804,8 @@ { int status = 0; + WINPR_UNUSED(msg); + switch (type) { case Input_SynchronizeEvent: diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/nego.c freerdp2-2.3.0+dfsg1/libfreerdp/core/nego.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/nego.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/nego.c 2021-02-25 08:51:41.000000000 +0000 @@ -1067,17 +1067,15 @@ em = Stream_GetPosition(s); Stream_SetPosition(s, bm); - tpkt_write_header(s, length); - tpdu_write_connection_confirm(s, length - 5); - Stream_SetPosition(s, em); - Stream_SealLength(s); - - if (transport_write(nego->transport, s) < 0) + status = tpkt_write_header(s, length); + if (status) { - Stream_Free(s, TRUE); - return FALSE; - } + tpdu_write_connection_confirm(s, length - 5); + Stream_SetPosition(s, em); + Stream_SealLength(s); + status = (transport_write(nego->transport, s) >= 0); + } Stream_Free(s, TRUE); if (status) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/nla.c freerdp2-2.3.0+dfsg1/libfreerdp/core/nla.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/nla.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/nla.c 2021-02-25 08:51:41.000000000 +0000 @@ -144,8 +144,8 @@ SecPkgContext_Sizes ContextSizes; }; -static BOOL nla_send(rdpNla* nla); -static int nla_recv(rdpNla* nla); +static BOOL nla_send(rdpNla* nla, const char* msg); +static int nla_recv(rdpNla* nla, const char* msg); static void nla_buffer_print(rdpNla* nla); static void nla_buffer_free(rdpNla* nla); static SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla); @@ -520,12 +520,8 @@ nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer; nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer; - WLog_DBG(TAG, "Sending Authentication Token"); -#if defined(WITH_DEBUG_NLA) - winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer); -#endif - if (!nla_send(nla)) + if (!nla_send(nla, "Client: Sending Authentication Token")) { nla_buffer_free(nla); return -1; @@ -613,12 +609,8 @@ nla->negoToken.pvBuffer = nla->outputBuffer.pvBuffer; nla->negoToken.cbBuffer = nla->outputBuffer.cbBuffer; - WLog_DBG(TAG, "Sending Authentication Token"); -#if defined(WITH_DEBUG_NLA) - winpr_HexDump(TAG, WLOG_DEBUG, nla->negoToken.pvBuffer, nla->negoToken.cbBuffer); -#endif - if (!nla_send(nla)) + if (!nla_send(nla, "Client: Sending Authentication Token")) { nla_buffer_free(nla); return -1; @@ -658,7 +650,7 @@ return -1; } - if (!nla_send(nla)) + if (!nla_send(nla, "Client: Sending PubKeyAuth Token")) { nla_buffer_free(nla); return -1; @@ -848,11 +840,9 @@ nla->inputBufferDesc.pBuffers = &nla->inputBuffer; nla->inputBuffer.BufferType = SECBUFFER_TOKEN; - if (nla_recv(nla) < 0) + if (nla_recv(nla, "Receiving Authentication Token") < 0) return -1; - WLog_DBG(TAG, "Receiving Authentication Token"); - nla_buffer_print(nla); nla->inputBuffer.pvBuffer = nla->negoToken.pvBuffer; nla->inputBuffer.cbBuffer = nla->negoToken.cbBuffer; @@ -935,17 +925,14 @@ { if (nla->outputBuffer.cbBuffer != 0) { - if (!nla_send(nla)) + if (!nla_send(nla, "Server: Sending response")) { nla_buffer_free(nla); return -1; } - if (nla_recv(nla) < 0) + if (nla_recv(nla, "Receiving pubkey Token") < 0) return -1; - - WLog_DBG(TAG, "Receiving pubkey Token"); - nla_buffer_print(nla); } nla->havePubKeyAuth = TRUE; @@ -1012,15 +999,12 @@ WLog_ERR(TAG, "AcceptSecurityContext status %s [0x%08" PRIX32 "]", GetSecurityStatusString(nla->status), nla->status); - nla_send(nla); + nla_send(nla, "Server: Sending AcceptSecurityContext error status"); return -1; /* Access Denied */ } /* send authentication token */ - WLog_DBG(TAG, "Sending Authentication Token"); - nla_buffer_print(nla); - - if (!nla_send(nla)) + if (!nla_send(nla, "Server: Sending Authentication Token")) { nla_buffer_free(nla); return -1; @@ -1036,7 +1020,7 @@ /* Receive encrypted credentials */ - if (nla_recv(nla) < 0) + if (nla_recv(nla, "Receive Encryption Credentials") < 0) return -1; nla->status = nla_decrypt_ts_credentials(nla); @@ -1916,7 +1900,7 @@ * @param credssp */ -BOOL nla_send(rdpNla* nla) +BOOL nla_send(rdpNla* nla, const char* msg) { BOOL rc = TRUE; wStream* s; @@ -1928,6 +1912,9 @@ size_t error_code_context_length = 0; size_t error_code_length = 0; size_t client_nonce_length = 0; + WLog_DBG(TAG, "%s", msg); + nla_buffer_print(nla); + nego_tokens_length = (nla->negoToken.cbBuffer > 0) ? nla_sizeof_nego_tokens(nla->negoToken.cbBuffer) : 0; pub_key_auth_length = @@ -2115,6 +2102,8 @@ { if (!ber_read_integer(s, &nla->errorCode)) return -1; + WLog_WARN(TAG, "SPNEGO received NTSTATUS: %s [0x%08" PRIX32 "] from server", + GetSecurityStatusString(nla->errorCode), nla->errorCode); } if (nla->peerVersion >= 5) @@ -2190,7 +2179,8 @@ break; default: - WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: 0x%08" PRIX32 "", nla->errorCode); + WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: %s [0x%08" PRIX32 "]", + GetSecurityStatusString(nla->errorCode), nla->errorCode); code = FREERDP_ERROR_AUTHENTICATION_FAILED; break; } @@ -2205,7 +2195,7 @@ return 1; } -int nla_recv(rdpNla* nla) +int nla_recv(rdpNla* nla, const char* msg) { wStream* s; int status; @@ -2213,7 +2203,7 @@ if (!s) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_ERR(TAG, "[%s] Stream_New failed!", __FUNCTION__); return -1; } @@ -2221,18 +2211,21 @@ if (status < 0) { - WLog_ERR(TAG, "nla_recv() error: %d", status); + WLog_ERR(TAG, "[%s] error: %d", __FUNCTION__, status); Stream_Free(s, TRUE); return -1; } if (nla_decode_ts_request(nla, s) < 1) { + WLog_ERR(TAG, "[%s] Invalid data received, aborting", __FUNCTION__); Stream_Free(s, TRUE); return -1; } Stream_Free(s, TRUE); + WLog_DBG(TAG, "[%s] %s", __FUNCTION__, msg); + nla_buffer_print(nla); return 1; } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/orders.c freerdp2-2.3.0+dfsg1/libfreerdp/core/orders.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/orders.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/orders.c 2021-02-25 08:51:41.000000000 +0000 @@ -1061,76 +1061,95 @@ return TRUE; } -#define ORDER_FIELD_BYTE(NO, TARGET) \ - do \ - { \ - if (orderInfo->fieldFlags & (1 << (NO - 1))) \ - { \ - if (Stream_GetRemainingLength(s) < 1) \ - { \ - WLog_ERR(TAG, "error reading %s", #TARGET); \ - return FALSE; \ - } \ - Stream_Read_UINT8(s, TARGET); \ - } \ - } while (0) -#define ORDER_FIELD_2BYTE(NO, TARGET1, TARGET2) \ - do \ - { \ - if (orderInfo->fieldFlags & (1 << (NO - 1))) \ - { \ - if (Stream_GetRemainingLength(s) < 2) \ - { \ - WLog_ERR(TAG, "error reading %s or %s", #TARGET1, #TARGET2); \ - return FALSE; \ - } \ - Stream_Read_UINT8(s, TARGET1); \ - Stream_Read_UINT8(s, TARGET2); \ - } \ - } while (0) -#define ORDER_FIELD_UINT16(NO, TARGET) \ - do \ - { \ - if (orderInfo->fieldFlags & (1 << (NO - 1))) \ - { \ - if (Stream_GetRemainingLength(s) < 2) \ - { \ - WLog_ERR(TAG, "error reading %s", #TARGET); \ - return FALSE; \ - } \ - Stream_Read_UINT16(s, TARGET); \ - } \ - } while (0) -#define ORDER_FIELD_UINT32(NO, TARGET) \ - do \ - { \ - if (orderInfo->fieldFlags & (1 << (NO - 1))) \ - { \ - if (Stream_GetRemainingLength(s) < 4) \ - { \ - WLog_ERR(TAG, "error reading %s", #TARGET); \ - return FALSE; \ - } \ - Stream_Read_UINT32(s, TARGET); \ - } \ - } while (0) -#define ORDER_FIELD_COORD(NO, TARGET) \ - do \ - { \ - if ((orderInfo->fieldFlags & (1 << (NO - 1))) && \ - !update_read_coord(s, &TARGET, orderInfo->deltaCoordinates)) \ - { \ - WLog_ERR(TAG, "error reading %s", #TARGET); \ - return FALSE; \ - } \ - } while (0) -static INLINE BOOL ORDER_FIELD_COLOR(const ORDER_INFO* orderInfo, wStream* s, UINT32 NO, - UINT32* TARGET) + +static BOOL order_field_flag_is_set(const ORDER_INFO* orderInfo, BYTE number) +{ + const UINT32 mask = (1UL << ((UINT32)number - 1UL)); + const BOOL set = (orderInfo->fieldFlags & mask) != 0; + return set; +} + +static INLINE BOOL read_order_field_byte(const ORDER_INFO* orderInfo, wStream* s, BYTE number, + UINT32* target, BOOL optional) +{ + if (!order_field_flag_is_set(orderInfo, number)) + return TRUE; + if (Stream_GetRemainingLength(s) < 1) + return FALSE; + Stream_Read_UINT8(s, *target); + return TRUE; +} + +static INLINE BOOL read_order_field_2bytes(const ORDER_INFO* orderInfo, wStream* s, BYTE number, + UINT32* target1, UINT32* target2, BOOL optional) +{ + if (!order_field_flag_is_set(orderInfo, number)) + return TRUE; + if (Stream_GetRemainingLength(s) < 2) + return FALSE; + Stream_Read_UINT8(s, *target1); + Stream_Read_UINT8(s, *target2); + return TRUE; +} + +static INLINE BOOL read_order_field_uint16(const ORDER_INFO* orderInfo, wStream* s, BYTE number, + UINT32* target, BOOL optional) +{ + if (!order_field_flag_is_set(orderInfo, number)) + return TRUE; + + if (Stream_GetRemainingLength(s) < 2) + return FALSE; + + Stream_Read_UINT16(s, *target); + return TRUE; +} + +static INLINE BOOL read_order_field_int16(const ORDER_INFO* orderInfo, wStream* s, BYTE number, + INT32* target, BOOL optional) +{ + if (!order_field_flag_is_set(orderInfo, number)) + return TRUE; + + if (Stream_GetRemainingLength(s) < 2) + return FALSE; + + Stream_Read_INT16(s, *target); + return TRUE; +} + +static INLINE BOOL read_order_field_uint32(const ORDER_INFO* orderInfo, wStream* s, BYTE number, + UINT32* target, BOOL optional) +{ + if (!order_field_flag_is_set(orderInfo, number)) + return TRUE; + if (Stream_GetRemainingLength(s) < 4) + return FALSE; + + Stream_Read_UINT32(s, *target); + return TRUE; +} + +static INLINE BOOL read_order_field_coord(const ORDER_INFO* orderInfo, wStream* s, UINT32 NO, + INT32* TARGET, BOOL optional) { if (!TARGET || !orderInfo) return FALSE; + if (!order_field_flag_is_set(orderInfo, NO)) + return TRUE; + + return update_read_coord(s, TARGET, orderInfo->deltaCoordinates); +} - if ((orderInfo->fieldFlags & (1 << (NO - 1))) && !update_read_color(s, TARGET)) +static INLINE BOOL read_order_field_color(const ORDER_INFO* orderInfo, wStream* s, UINT32 NO, + UINT32* TARGET, BOOL optional) +{ + if (!TARGET || !orderInfo) + return FALSE; + if (!order_field_flag_is_set(orderInfo, NO)) + return TRUE; + + if (!update_read_color(s, TARGET)) return FALSE; return TRUE; @@ -1153,12 +1172,13 @@ /* Primary Drawing Orders */ static BOOL update_read_dstblt_order(wStream* s, const ORDER_INFO* orderInfo, DSTBLT_ORDER* dstblt) { - ORDER_FIELD_COORD(1, dstblt->nLeftRect); - ORDER_FIELD_COORD(2, dstblt->nTopRect); - ORDER_FIELD_COORD(3, dstblt->nWidth); - ORDER_FIELD_COORD(4, dstblt->nHeight); - ORDER_FIELD_BYTE(5, dstblt->bRop); - return TRUE; + if (read_order_field_coord(orderInfo, s, 1, &dstblt->nLeftRect, FALSE) && + read_order_field_coord(orderInfo, s, 2, &dstblt->nTopRect, FALSE) && + read_order_field_coord(orderInfo, s, 3, &dstblt->nWidth, FALSE) && + read_order_field_coord(orderInfo, s, 4, &dstblt->nHeight, FALSE) && + read_order_field_byte(orderInfo, s, 5, &dstblt->bRop, TRUE)) + return TRUE; + return FALSE; } int update_approximate_dstblt_order(ORDER_INFO* orderInfo, const DSTBLT_ORDER* dstblt) { @@ -1184,14 +1204,16 @@ } static BOOL update_read_patblt_order(wStream* s, const ORDER_INFO* orderInfo, PATBLT_ORDER* patblt) { - ORDER_FIELD_COORD(1, patblt->nLeftRect); - ORDER_FIELD_COORD(2, patblt->nTopRect); - ORDER_FIELD_COORD(3, patblt->nWidth); - ORDER_FIELD_COORD(4, patblt->nHeight); - ORDER_FIELD_BYTE(5, patblt->bRop); - ORDER_FIELD_COLOR(orderInfo, s, 6, &patblt->backColor); - ORDER_FIELD_COLOR(orderInfo, s, 7, &patblt->foreColor); - return update_read_brush(s, &patblt->brush, orderInfo->fieldFlags >> 7); + if (read_order_field_coord(orderInfo, s, 1, &patblt->nLeftRect, FALSE) && + read_order_field_coord(orderInfo, s, 2, &patblt->nTopRect, FALSE) && + read_order_field_coord(orderInfo, s, 3, &patblt->nWidth, FALSE) && + read_order_field_coord(orderInfo, s, 4, &patblt->nHeight, FALSE) && + read_order_field_byte(orderInfo, s, 5, &patblt->bRop, TRUE) && + read_order_field_color(orderInfo, s, 6, &patblt->backColor, TRUE) && + read_order_field_color(orderInfo, s, 7, &patblt->foreColor, TRUE) && + update_read_brush(s, &patblt->brush, orderInfo->fieldFlags >> 7)) + return TRUE; + return FALSE; } int update_approximate_patblt_order(ORDER_INFO* orderInfo, PATBLT_ORDER* patblt) { @@ -1227,14 +1249,15 @@ } static BOOL update_read_scrblt_order(wStream* s, const ORDER_INFO* orderInfo, SCRBLT_ORDER* scrblt) { - ORDER_FIELD_COORD(1, scrblt->nLeftRect); - ORDER_FIELD_COORD(2, scrblt->nTopRect); - ORDER_FIELD_COORD(3, scrblt->nWidth); - ORDER_FIELD_COORD(4, scrblt->nHeight); - ORDER_FIELD_BYTE(5, scrblt->bRop); - ORDER_FIELD_COORD(6, scrblt->nXSrc); - ORDER_FIELD_COORD(7, scrblt->nYSrc); - return TRUE; + if (read_order_field_coord(orderInfo, s, 1, &scrblt->nLeftRect, FALSE) && + read_order_field_coord(orderInfo, s, 2, &scrblt->nTopRect, FALSE) && + read_order_field_coord(orderInfo, s, 3, &scrblt->nWidth, FALSE) && + read_order_field_coord(orderInfo, s, 4, &scrblt->nHeight, FALSE) && + read_order_field_byte(orderInfo, s, 5, &scrblt->bRop, TRUE) && + read_order_field_coord(orderInfo, s, 6, &scrblt->nXSrc, FALSE) && + read_order_field_coord(orderInfo, s, 7, &scrblt->nYSrc, FALSE)) + return TRUE; + return FALSE; } int update_approximate_scrblt_order(ORDER_INFO* orderInfo, const SCRBLT_ORDER* scrblt) { @@ -1266,12 +1289,13 @@ OPAQUE_RECT_ORDER* opaque_rect) { BYTE byte; - ORDER_FIELD_COORD(1, opaque_rect->nLeftRect); - ORDER_FIELD_COORD(2, opaque_rect->nTopRect); - ORDER_FIELD_COORD(3, opaque_rect->nWidth); - ORDER_FIELD_COORD(4, opaque_rect->nHeight); + if (!read_order_field_coord(orderInfo, s, 1, &opaque_rect->nLeftRect, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &opaque_rect->nTopRect, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &opaque_rect->nWidth, FALSE) || + !read_order_field_coord(orderInfo, s, 4, &opaque_rect->nHeight, FALSE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_05) + if ((orderInfo->fieldFlags & ORDER_FIELD_05) != 0) { if (Stream_GetRemainingLength(s) < 1) return FALSE; @@ -1280,7 +1304,7 @@ opaque_rect->color = (opaque_rect->color & 0x00FFFF00) | ((UINT32)byte); } - if (orderInfo->fieldFlags & ORDER_FIELD_06) + if ((orderInfo->fieldFlags & ORDER_FIELD_06) != 0) { if (Stream_GetRemainingLength(s) < 1) return FALSE; @@ -1289,7 +1313,7 @@ opaque_rect->color = (opaque_rect->color & 0x00FF00FF) | ((UINT32)byte << 8); } - if (orderInfo->fieldFlags & ORDER_FIELD_07) + if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) { if (Stream_GetRemainingLength(s) < 1) return FALSE; @@ -1338,24 +1362,26 @@ static BOOL update_read_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo, DRAW_NINE_GRID_ORDER* draw_nine_grid) { - ORDER_FIELD_COORD(1, draw_nine_grid->srcLeft); - ORDER_FIELD_COORD(2, draw_nine_grid->srcTop); - ORDER_FIELD_COORD(3, draw_nine_grid->srcRight); - ORDER_FIELD_COORD(4, draw_nine_grid->srcBottom); - ORDER_FIELD_UINT16(5, draw_nine_grid->bitmapId); - return TRUE; + if (read_order_field_coord(orderInfo, s, 1, &draw_nine_grid->srcLeft, FALSE) && + read_order_field_coord(orderInfo, s, 2, &draw_nine_grid->srcTop, FALSE) && + read_order_field_coord(orderInfo, s, 3, &draw_nine_grid->srcRight, FALSE) && + read_order_field_coord(orderInfo, s, 4, &draw_nine_grid->srcBottom, FALSE) && + read_order_field_uint16(orderInfo, s, 5, &draw_nine_grid->bitmapId, FALSE)) + return TRUE; + return FALSE; } static BOOL update_read_multi_dstblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_DSTBLT_ORDER* multi_dstblt) { - ORDER_FIELD_COORD(1, multi_dstblt->nLeftRect); - ORDER_FIELD_COORD(2, multi_dstblt->nTopRect); - ORDER_FIELD_COORD(3, multi_dstblt->nWidth); - ORDER_FIELD_COORD(4, multi_dstblt->nHeight); - ORDER_FIELD_BYTE(5, multi_dstblt->bRop); - ORDER_FIELD_BYTE(6, multi_dstblt->numRectangles); + if (!read_order_field_coord(orderInfo, s, 1, &multi_dstblt->nLeftRect, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &multi_dstblt->nTopRect, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &multi_dstblt->nWidth, FALSE) || + !read_order_field_coord(orderInfo, s, 4, &multi_dstblt->nHeight, FALSE) || + !read_order_field_byte(orderInfo, s, 5, &multi_dstblt->bRop, TRUE) || + !read_order_field_byte(orderInfo, s, 6, &multi_dstblt->numRectangles, TRUE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_07) + if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) { if (Stream_GetRemainingLength(s) < 2) return FALSE; @@ -1369,20 +1395,22 @@ static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_PATBLT_ORDER* multi_patblt) { - ORDER_FIELD_COORD(1, multi_patblt->nLeftRect); - ORDER_FIELD_COORD(2, multi_patblt->nTopRect); - ORDER_FIELD_COORD(3, multi_patblt->nWidth); - ORDER_FIELD_COORD(4, multi_patblt->nHeight); - ORDER_FIELD_BYTE(5, multi_patblt->bRop); - ORDER_FIELD_COLOR(orderInfo, s, 6, &multi_patblt->backColor); - ORDER_FIELD_COLOR(orderInfo, s, 7, &multi_patblt->foreColor); + if (!read_order_field_coord(orderInfo, s, 1, &multi_patblt->nLeftRect, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &multi_patblt->nTopRect, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &multi_patblt->nWidth, FALSE) || + !read_order_field_coord(orderInfo, s, 4, &multi_patblt->nHeight, FALSE) || + !read_order_field_byte(orderInfo, s, 5, &multi_patblt->bRop, TRUE) || + !read_order_field_color(orderInfo, s, 6, &multi_patblt->backColor, TRUE) || + !read_order_field_color(orderInfo, s, 7, &multi_patblt->foreColor, TRUE)) + return FALSE; if (!update_read_brush(s, &multi_patblt->brush, orderInfo->fieldFlags >> 7)) return FALSE; - ORDER_FIELD_BYTE(13, multi_patblt->numRectangles); + if (!read_order_field_byte(orderInfo, s, 13, &multi_patblt->numRectangles, TRUE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_14) + if ((orderInfo->fieldFlags & ORDER_FIELD_14) != 0) { if (Stream_GetRemainingLength(s) < 2) return FALSE; @@ -1398,16 +1426,17 @@ static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_SCRBLT_ORDER* multi_scrblt) { - ORDER_FIELD_COORD(1, multi_scrblt->nLeftRect); - ORDER_FIELD_COORD(2, multi_scrblt->nTopRect); - ORDER_FIELD_COORD(3, multi_scrblt->nWidth); - ORDER_FIELD_COORD(4, multi_scrblt->nHeight); - ORDER_FIELD_BYTE(5, multi_scrblt->bRop); - ORDER_FIELD_COORD(6, multi_scrblt->nXSrc); - ORDER_FIELD_COORD(7, multi_scrblt->nYSrc); - ORDER_FIELD_BYTE(8, multi_scrblt->numRectangles); + if (!read_order_field_coord(orderInfo, s, 1, &multi_scrblt->nLeftRect, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &multi_scrblt->nTopRect, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &multi_scrblt->nWidth, FALSE) || + !read_order_field_coord(orderInfo, s, 4, &multi_scrblt->nHeight, FALSE) || + !read_order_field_byte(orderInfo, s, 5, &multi_scrblt->bRop, TRUE) || + !read_order_field_coord(orderInfo, s, 6, &multi_scrblt->nXSrc, FALSE) || + !read_order_field_coord(orderInfo, s, 7, &multi_scrblt->nYSrc, FALSE) || + !read_order_field_byte(orderInfo, s, 8, &multi_scrblt->numRectangles, TRUE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_09) + if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0) { if (Stream_GetRemainingLength(s) < 2) return FALSE; @@ -1422,12 +1451,13 @@ MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect) { BYTE byte; - ORDER_FIELD_COORD(1, multi_opaque_rect->nLeftRect); - ORDER_FIELD_COORD(2, multi_opaque_rect->nTopRect); - ORDER_FIELD_COORD(3, multi_opaque_rect->nWidth); - ORDER_FIELD_COORD(4, multi_opaque_rect->nHeight); + if (!read_order_field_coord(orderInfo, s, 1, &multi_opaque_rect->nLeftRect, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &multi_opaque_rect->nTopRect, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &multi_opaque_rect->nWidth, FALSE) || + !read_order_field_coord(orderInfo, s, 4, &multi_opaque_rect->nHeight, FALSE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_05) + if ((orderInfo->fieldFlags & ORDER_FIELD_05) != 0) { if (Stream_GetRemainingLength(s) < 1) return FALSE; @@ -1436,7 +1466,7 @@ multi_opaque_rect->color = (multi_opaque_rect->color & 0x00FFFF00) | ((UINT32)byte); } - if (orderInfo->fieldFlags & ORDER_FIELD_06) + if ((orderInfo->fieldFlags & ORDER_FIELD_06) != 0) { if (Stream_GetRemainingLength(s) < 1) return FALSE; @@ -1445,7 +1475,7 @@ multi_opaque_rect->color = (multi_opaque_rect->color & 0x00FF00FF) | ((UINT32)byte << 8); } - if (orderInfo->fieldFlags & ORDER_FIELD_07) + if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) { if (Stream_GetRemainingLength(s) < 1) return FALSE; @@ -1454,9 +1484,10 @@ multi_opaque_rect->color = (multi_opaque_rect->color & 0x0000FFFF) | ((UINT32)byte << 16); } - ORDER_FIELD_BYTE(8, multi_opaque_rect->numRectangles); + if (!read_order_field_byte(orderInfo, s, 8, &multi_opaque_rect->numRectangles, TRUE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_09) + if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0) { if (Stream_GetRemainingLength(s) < 2) return FALSE; @@ -1471,14 +1502,15 @@ static BOOL update_read_multi_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid) { - ORDER_FIELD_COORD(1, multi_draw_nine_grid->srcLeft); - ORDER_FIELD_COORD(2, multi_draw_nine_grid->srcTop); - ORDER_FIELD_COORD(3, multi_draw_nine_grid->srcRight); - ORDER_FIELD_COORD(4, multi_draw_nine_grid->srcBottom); - ORDER_FIELD_UINT16(5, multi_draw_nine_grid->bitmapId); - ORDER_FIELD_BYTE(6, multi_draw_nine_grid->nDeltaEntries); + if (!read_order_field_coord(orderInfo, s, 1, &multi_draw_nine_grid->srcLeft, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &multi_draw_nine_grid->srcTop, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &multi_draw_nine_grid->srcRight, FALSE) || + !read_order_field_coord(orderInfo, s, 4, &multi_draw_nine_grid->srcBottom, FALSE) || + !read_order_field_uint16(orderInfo, s, 5, &multi_draw_nine_grid->bitmapId, TRUE) || + !read_order_field_byte(orderInfo, s, 6, &multi_draw_nine_grid->nDeltaEntries, TRUE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_07) + if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) { if (Stream_GetRemainingLength(s) < 2) return FALSE; @@ -1493,17 +1525,18 @@ static BOOL update_read_line_to_order(wStream* s, const ORDER_INFO* orderInfo, LINE_TO_ORDER* line_to) { - ORDER_FIELD_UINT16(1, line_to->backMode); - ORDER_FIELD_COORD(2, line_to->nXStart); - ORDER_FIELD_COORD(3, line_to->nYStart); - ORDER_FIELD_COORD(4, line_to->nXEnd); - ORDER_FIELD_COORD(5, line_to->nYEnd); - ORDER_FIELD_COLOR(orderInfo, s, 6, &line_to->backColor); - ORDER_FIELD_BYTE(7, line_to->bRop2); - ORDER_FIELD_BYTE(8, line_to->penStyle); - ORDER_FIELD_BYTE(9, line_to->penWidth); - ORDER_FIELD_COLOR(orderInfo, s, 10, &line_to->penColor); - return TRUE; + if (read_order_field_uint16(orderInfo, s, 1, &line_to->backMode, TRUE) && + read_order_field_coord(orderInfo, s, 2, &line_to->nXStart, FALSE) && + read_order_field_coord(orderInfo, s, 3, &line_to->nYStart, FALSE) && + read_order_field_coord(orderInfo, s, 4, &line_to->nXEnd, FALSE) && + read_order_field_coord(orderInfo, s, 5, &line_to->nYEnd, FALSE) && + read_order_field_color(orderInfo, s, 6, &line_to->backColor, TRUE) && + read_order_field_byte(orderInfo, s, 7, &line_to->bRop2, TRUE) && + read_order_field_byte(orderInfo, s, 8, &line_to->penStyle, TRUE) && + read_order_field_byte(orderInfo, s, 9, &line_to->penWidth, TRUE) && + read_order_field_color(orderInfo, s, 10, &line_to->penColor, TRUE)) + return TRUE; + return FALSE; } int update_approximate_line_to_order(ORDER_INFO* orderInfo, const LINE_TO_ORDER* line_to) { @@ -1540,16 +1573,17 @@ static BOOL update_read_polyline_order(wStream* s, const ORDER_INFO* orderInfo, POLYLINE_ORDER* polyline) { - UINT16 word; + UINT32 word; UINT32 new_num = polyline->numDeltaEntries; - ORDER_FIELD_COORD(1, polyline->xStart); - ORDER_FIELD_COORD(2, polyline->yStart); - ORDER_FIELD_BYTE(3, polyline->bRop2); - ORDER_FIELD_UINT16(4, word); - ORDER_FIELD_COLOR(orderInfo, s, 5, &polyline->penColor); - ORDER_FIELD_BYTE(6, new_num); + if (!read_order_field_coord(orderInfo, s, 1, &polyline->xStart, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &polyline->yStart, FALSE) || + !read_order_field_byte(orderInfo, s, 3, &polyline->bRop2, TRUE) || + !read_order_field_uint16(orderInfo, s, 4, &word, TRUE) || + !read_order_field_color(orderInfo, s, 5, &polyline->penColor, TRUE) || + !read_order_field_byte(orderInfo, s, 6, &new_num, TRUE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_07) + if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) { DELTA_POINT* new_points; @@ -1584,15 +1618,16 @@ if (!s || !orderInfo || !memblt) return FALSE; - ORDER_FIELD_UINT16(1, memblt->cacheId); - ORDER_FIELD_COORD(2, memblt->nLeftRect); - ORDER_FIELD_COORD(3, memblt->nTopRect); - ORDER_FIELD_COORD(4, memblt->nWidth); - ORDER_FIELD_COORD(5, memblt->nHeight); - ORDER_FIELD_BYTE(6, memblt->bRop); - ORDER_FIELD_COORD(7, memblt->nXSrc); - ORDER_FIELD_COORD(8, memblt->nYSrc); - ORDER_FIELD_UINT16(9, memblt->cacheIndex); + if (!read_order_field_uint16(orderInfo, s, 1, &memblt->cacheId, TRUE) || + !read_order_field_coord(orderInfo, s, 2, &memblt->nLeftRect, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &memblt->nTopRect, FALSE) || + !read_order_field_coord(orderInfo, s, 4, &memblt->nWidth, FALSE) || + !read_order_field_coord(orderInfo, s, 5, &memblt->nHeight, FALSE) || + !read_order_field_byte(orderInfo, s, 6, &memblt->bRop, TRUE) || + !read_order_field_coord(orderInfo, s, 7, &memblt->nXSrc, FALSE) || + !read_order_field_coord(orderInfo, s, 8, &memblt->nYSrc, FALSE) || + !read_order_field_uint16(orderInfo, s, 9, &memblt->cacheIndex, TRUE)) + return FALSE; memblt->colorIndex = (memblt->cacheId >> 8); memblt->cacheId = (memblt->cacheId & 0xFF); memblt->bitmap = NULL; @@ -1633,21 +1668,21 @@ static BOOL update_read_mem3blt_order(wStream* s, const ORDER_INFO* orderInfo, MEM3BLT_ORDER* mem3blt) { - ORDER_FIELD_UINT16(1, mem3blt->cacheId); - ORDER_FIELD_COORD(2, mem3blt->nLeftRect); - ORDER_FIELD_COORD(3, mem3blt->nTopRect); - ORDER_FIELD_COORD(4, mem3blt->nWidth); - ORDER_FIELD_COORD(5, mem3blt->nHeight); - ORDER_FIELD_BYTE(6, mem3blt->bRop); - ORDER_FIELD_COORD(7, mem3blt->nXSrc); - ORDER_FIELD_COORD(8, mem3blt->nYSrc); - ORDER_FIELD_COLOR(orderInfo, s, 9, &mem3blt->backColor); - ORDER_FIELD_COLOR(orderInfo, s, 10, &mem3blt->foreColor); - - if (!update_read_brush(s, &mem3blt->brush, orderInfo->fieldFlags >> 10)) + if (!read_order_field_uint16(orderInfo, s, 1, &mem3blt->cacheId, TRUE) || + !read_order_field_coord(orderInfo, s, 2, &mem3blt->nLeftRect, FALSE) || + !read_order_field_coord(orderInfo, s, 3, &mem3blt->nTopRect, FALSE) || + !read_order_field_coord(orderInfo, s, 4, &mem3blt->nWidth, FALSE) || + !read_order_field_coord(orderInfo, s, 5, &mem3blt->nHeight, FALSE) || + !read_order_field_byte(orderInfo, s, 6, &mem3blt->bRop, TRUE) || + !read_order_field_coord(orderInfo, s, 7, &mem3blt->nXSrc, FALSE) || + !read_order_field_coord(orderInfo, s, 8, &mem3blt->nYSrc, FALSE) || + !read_order_field_color(orderInfo, s, 9, &mem3blt->backColor, TRUE) || + !read_order_field_color(orderInfo, s, 10, &mem3blt->foreColor, TRUE)) return FALSE; - ORDER_FIELD_UINT16(16, mem3blt->cacheIndex); + if (!update_read_brush(s, &mem3blt->brush, orderInfo->fieldFlags >> 10) || + !read_order_field_uint16(orderInfo, s, 16, &mem3blt->cacheIndex, TRUE)) + return FALSE; mem3blt->colorIndex = (mem3blt->cacheId >> 8); mem3blt->cacheId = (mem3blt->cacheId & 0xFF); mem3blt->bitmap = NULL; @@ -1656,39 +1691,38 @@ static BOOL update_read_save_bitmap_order(wStream* s, const ORDER_INFO* orderInfo, SAVE_BITMAP_ORDER* save_bitmap) { - ORDER_FIELD_UINT32(1, save_bitmap->savedBitmapPosition); - ORDER_FIELD_COORD(2, save_bitmap->nLeftRect); - ORDER_FIELD_COORD(3, save_bitmap->nTopRect); - ORDER_FIELD_COORD(4, save_bitmap->nRightRect); - ORDER_FIELD_COORD(5, save_bitmap->nBottomRect); - ORDER_FIELD_BYTE(6, save_bitmap->operation); - return TRUE; + if (read_order_field_uint32(orderInfo, s, 1, &save_bitmap->savedBitmapPosition, TRUE) && + read_order_field_coord(orderInfo, s, 2, &save_bitmap->nLeftRect, FALSE) && + read_order_field_coord(orderInfo, s, 3, &save_bitmap->nTopRect, FALSE) && + read_order_field_coord(orderInfo, s, 4, &save_bitmap->nRightRect, FALSE) && + read_order_field_coord(orderInfo, s, 5, &save_bitmap->nBottomRect, FALSE) && + read_order_field_byte(orderInfo, s, 6, &save_bitmap->operation, TRUE)) + return TRUE; + return FALSE; } static BOOL update_read_glyph_index_order(wStream* s, const ORDER_INFO* orderInfo, GLYPH_INDEX_ORDER* glyph_index) { - ORDER_FIELD_BYTE(1, glyph_index->cacheId); - ORDER_FIELD_BYTE(2, glyph_index->flAccel); - ORDER_FIELD_BYTE(3, glyph_index->ulCharInc); - ORDER_FIELD_BYTE(4, glyph_index->fOpRedundant); - ORDER_FIELD_COLOR(orderInfo, s, 5, &glyph_index->backColor); - ORDER_FIELD_COLOR(orderInfo, s, 6, &glyph_index->foreColor); - ORDER_FIELD_UINT16(7, glyph_index->bkLeft); - ORDER_FIELD_UINT16(8, glyph_index->bkTop); - ORDER_FIELD_UINT16(9, glyph_index->bkRight); - ORDER_FIELD_UINT16(10, glyph_index->bkBottom); - ORDER_FIELD_UINT16(11, glyph_index->opLeft); - ORDER_FIELD_UINT16(12, glyph_index->opTop); - ORDER_FIELD_UINT16(13, glyph_index->opRight); - ORDER_FIELD_UINT16(14, glyph_index->opBottom); - - if (!update_read_brush(s, &glyph_index->brush, orderInfo->fieldFlags >> 14)) + if (!read_order_field_byte(orderInfo, s, 1, &glyph_index->cacheId, TRUE) || + !read_order_field_byte(orderInfo, s, 2, &glyph_index->flAccel, TRUE) || + !read_order_field_byte(orderInfo, s, 3, &glyph_index->ulCharInc, TRUE) || + !read_order_field_byte(orderInfo, s, 4, &glyph_index->fOpRedundant, TRUE) || + !read_order_field_color(orderInfo, s, 5, &glyph_index->backColor, TRUE) || + !read_order_field_color(orderInfo, s, 6, &glyph_index->foreColor, TRUE) || + !read_order_field_int16(orderInfo, s, 7, &glyph_index->bkLeft, TRUE) || + !read_order_field_int16(orderInfo, s, 8, &glyph_index->bkTop, TRUE) || + !read_order_field_int16(orderInfo, s, 9, &glyph_index->bkRight, TRUE) || + !read_order_field_int16(orderInfo, s, 10, &glyph_index->bkBottom, TRUE) || + !read_order_field_int16(orderInfo, s, 11, &glyph_index->opLeft, TRUE) || + !read_order_field_int16(orderInfo, s, 12, &glyph_index->opTop, TRUE) || + !read_order_field_int16(orderInfo, s, 13, &glyph_index->opRight, TRUE) || + !read_order_field_int16(orderInfo, s, 14, &glyph_index->opBottom, TRUE) || + !update_read_brush(s, &glyph_index->brush, orderInfo->fieldFlags >> 14) || + !read_order_field_int16(orderInfo, s, 20, &glyph_index->x, TRUE) || + !read_order_field_int16(orderInfo, s, 21, &glyph_index->y, TRUE)) return FALSE; - ORDER_FIELD_UINT16(20, glyph_index->x); - ORDER_FIELD_UINT16(21, glyph_index->y); - - if (orderInfo->fieldFlags & ORDER_FIELD_22) + if ((orderInfo->fieldFlags & ORDER_FIELD_22) != 0) { if (Stream_GetRemainingLength(s) < 1) return FALSE; @@ -1764,22 +1798,24 @@ static BOOL update_read_fast_index_order(wStream* s, const ORDER_INFO* orderInfo, FAST_INDEX_ORDER* fast_index) { - ORDER_FIELD_BYTE(1, fast_index->cacheId); - ORDER_FIELD_2BYTE(2, fast_index->ulCharInc, fast_index->flAccel); - ORDER_FIELD_COLOR(orderInfo, s, 3, &fast_index->backColor); - ORDER_FIELD_COLOR(orderInfo, s, 4, &fast_index->foreColor); - ORDER_FIELD_COORD(5, fast_index->bkLeft); - ORDER_FIELD_COORD(6, fast_index->bkTop); - ORDER_FIELD_COORD(7, fast_index->bkRight); - ORDER_FIELD_COORD(8, fast_index->bkBottom); - ORDER_FIELD_COORD(9, fast_index->opLeft); - ORDER_FIELD_COORD(10, fast_index->opTop); - ORDER_FIELD_COORD(11, fast_index->opRight); - ORDER_FIELD_COORD(12, fast_index->opBottom); - ORDER_FIELD_COORD(13, fast_index->x); - ORDER_FIELD_COORD(14, fast_index->y); + if (!read_order_field_byte(orderInfo, s, 1, &fast_index->cacheId, TRUE) || + !read_order_field_2bytes(orderInfo, s, 2, &fast_index->ulCharInc, &fast_index->flAccel, + TRUE) || + !read_order_field_color(orderInfo, s, 3, &fast_index->backColor, TRUE) || + !read_order_field_color(orderInfo, s, 4, &fast_index->foreColor, TRUE) || + !read_order_field_coord(orderInfo, s, 5, &fast_index->bkLeft, FALSE) || + !read_order_field_coord(orderInfo, s, 6, &fast_index->bkTop, FALSE) || + !read_order_field_coord(orderInfo, s, 7, &fast_index->bkRight, FALSE) || + !read_order_field_coord(orderInfo, s, 8, &fast_index->bkBottom, FALSE) || + !read_order_field_coord(orderInfo, s, 9, &fast_index->opLeft, FALSE) || + !read_order_field_coord(orderInfo, s, 10, &fast_index->opTop, FALSE) || + !read_order_field_coord(orderInfo, s, 11, &fast_index->opRight, FALSE) || + !read_order_field_coord(orderInfo, s, 12, &fast_index->opBottom, FALSE) || + !read_order_field_coord(orderInfo, s, 13, &fast_index->x, FALSE) || + !read_order_field_coord(orderInfo, s, 14, &fast_index->y, FALSE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_15) + if ((orderInfo->fieldFlags & ORDER_FIELD_15) != 0) { if (Stream_GetRemainingLength(s) < 1) return FALSE; @@ -1799,71 +1835,68 @@ FAST_GLYPH_ORDER* fastGlyph) { GLYPH_DATA_V2* glyph = &fastGlyph->glyphData; - ORDER_FIELD_BYTE(1, fastGlyph->cacheId); - ORDER_FIELD_2BYTE(2, fastGlyph->ulCharInc, fastGlyph->flAccel); - ORDER_FIELD_COLOR(orderInfo, s, 3, &fastGlyph->backColor); - ORDER_FIELD_COLOR(orderInfo, s, 4, &fastGlyph->foreColor); - ORDER_FIELD_COORD(5, fastGlyph->bkLeft); - ORDER_FIELD_COORD(6, fastGlyph->bkTop); - ORDER_FIELD_COORD(7, fastGlyph->bkRight); - ORDER_FIELD_COORD(8, fastGlyph->bkBottom); - ORDER_FIELD_COORD(9, fastGlyph->opLeft); - ORDER_FIELD_COORD(10, fastGlyph->opTop); - ORDER_FIELD_COORD(11, fastGlyph->opRight); - ORDER_FIELD_COORD(12, fastGlyph->opBottom); - ORDER_FIELD_COORD(13, fastGlyph->x); - ORDER_FIELD_COORD(14, fastGlyph->y); + if (!read_order_field_byte(orderInfo, s, 1, &fastGlyph->cacheId, TRUE)) + return FALSE; + if (fastGlyph->cacheId > 9) + return FALSE; + if (!read_order_field_2bytes(orderInfo, s, 2, &fastGlyph->ulCharInc, &fastGlyph->flAccel, + TRUE) || + !read_order_field_color(orderInfo, s, 3, &fastGlyph->backColor, TRUE) || + !read_order_field_color(orderInfo, s, 4, &fastGlyph->foreColor, TRUE) || + !read_order_field_coord(orderInfo, s, 5, &fastGlyph->bkLeft, FALSE) || + !read_order_field_coord(orderInfo, s, 6, &fastGlyph->bkTop, FALSE) || + !read_order_field_coord(orderInfo, s, 7, &fastGlyph->bkRight, FALSE) || + !read_order_field_coord(orderInfo, s, 8, &fastGlyph->bkBottom, FALSE) || + !read_order_field_coord(orderInfo, s, 9, &fastGlyph->opLeft, FALSE) || + !read_order_field_coord(orderInfo, s, 10, &fastGlyph->opTop, FALSE) || + !read_order_field_coord(orderInfo, s, 11, &fastGlyph->opRight, FALSE) || + !read_order_field_coord(orderInfo, s, 12, &fastGlyph->opBottom, FALSE) || + !read_order_field_coord(orderInfo, s, 13, &fastGlyph->x, FALSE) || + !read_order_field_coord(orderInfo, s, 14, &fastGlyph->y, FALSE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_15) + if ((orderInfo->fieldFlags & ORDER_FIELD_15) != 0) { + const BYTE* src; + wStream sub; if (Stream_GetRemainingLength(s) < 1) return FALSE; Stream_Read_UINT8(s, fastGlyph->cbData); - if (Stream_GetRemainingLength(s) < fastGlyph->cbData) + src = Stream_Pointer(s); + if (!Stream_SafeSeek(s, fastGlyph->cbData) || (fastGlyph->cbData == 0)) return FALSE; - CopyMemory(fastGlyph->data, Stream_Pointer(s), fastGlyph->cbData); - if (Stream_GetRemainingLength(s) < fastGlyph->cbData) - return FALSE; + CopyMemory(fastGlyph->data, src, fastGlyph->cbData); + Stream_StaticInit(&sub, fastGlyph->data, fastGlyph->cbData); - if (!Stream_SafeSeek(s, 1)) - return FALSE; + Stream_Read_UINT8(&sub, glyph->cacheIndex); if (fastGlyph->cbData > 1) { - UINT32 new_cb; - /* parse optional glyph data */ - glyph->cacheIndex = fastGlyph->data[0]; - - if (!update_read_2byte_signed(s, &glyph->x) || - !update_read_2byte_signed(s, &glyph->y) || - !update_read_2byte_unsigned(s, &glyph->cx) || - !update_read_2byte_unsigned(s, &glyph->cy)) + if (!update_read_2byte_signed(&sub, &glyph->x) || + !update_read_2byte_signed(&sub, &glyph->y) || + !update_read_2byte_unsigned(&sub, &glyph->cx) || + !update_read_2byte_unsigned(&sub, &glyph->cy)) return FALSE; - glyph->cb = ((glyph->cx + 7) / 8) * glyph->cy; - glyph->cb += ((glyph->cb % 4) > 0) ? 4 - (glyph->cb % 4) : 0; - new_cb = ((glyph->cx + 7) / 8) * glyph->cy; - new_cb += ((new_cb % 4) > 0) ? 4 - (new_cb % 4) : 0; - - if (fastGlyph->cbData < new_cb) - return FALSE; - - if (new_cb > 0) + glyph->cb = Stream_GetRemainingLength(&sub); + if (glyph->cb > 0) { - BYTE* new_aj; - new_aj = (BYTE*)realloc(glyph->aj, new_cb); + BYTE* new_aj = (BYTE*)realloc(glyph->aj, glyph->cb); if (!new_aj) return FALSE; glyph->aj = new_aj; - glyph->cb = new_cb; - Stream_Read(s, glyph->aj, glyph->cb); + Stream_Read(&sub, glyph->aj, glyph->cb); + } + else + { + free(glyph->aj); + glyph->aj = NULL; } - Stream_Seek(s, fastGlyph->cbData - new_cb); } } @@ -1873,14 +1906,15 @@ POLYGON_SC_ORDER* polygon_sc) { UINT32 num = polygon_sc->numPoints; - ORDER_FIELD_COORD(1, polygon_sc->xStart); - ORDER_FIELD_COORD(2, polygon_sc->yStart); - ORDER_FIELD_BYTE(3, polygon_sc->bRop2); - ORDER_FIELD_BYTE(4, polygon_sc->fillMode); - ORDER_FIELD_COLOR(orderInfo, s, 5, &polygon_sc->brushColor); - ORDER_FIELD_BYTE(6, num); + if (!read_order_field_coord(orderInfo, s, 1, &polygon_sc->xStart, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &polygon_sc->yStart, FALSE) || + !read_order_field_byte(orderInfo, s, 3, &polygon_sc->bRop2, TRUE) || + !read_order_field_byte(orderInfo, s, 4, &polygon_sc->fillMode, TRUE) || + !read_order_field_color(orderInfo, s, 5, &polygon_sc->brushColor, TRUE) || + !read_order_field_byte(orderInfo, s, 6, &num, TRUE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_07) + if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) { DELTA_POINT* newpoints; @@ -1908,19 +1942,21 @@ POLYGON_CB_ORDER* polygon_cb) { UINT32 num = polygon_cb->numPoints; - ORDER_FIELD_COORD(1, polygon_cb->xStart); - ORDER_FIELD_COORD(2, polygon_cb->yStart); - ORDER_FIELD_BYTE(3, polygon_cb->bRop2); - ORDER_FIELD_BYTE(4, polygon_cb->fillMode); - ORDER_FIELD_COLOR(orderInfo, s, 5, &polygon_cb->backColor); - ORDER_FIELD_COLOR(orderInfo, s, 6, &polygon_cb->foreColor); + if (!read_order_field_coord(orderInfo, s, 1, &polygon_cb->xStart, FALSE) || + !read_order_field_coord(orderInfo, s, 2, &polygon_cb->yStart, FALSE) || + !read_order_field_byte(orderInfo, s, 3, &polygon_cb->bRop2, TRUE) || + !read_order_field_byte(orderInfo, s, 4, &polygon_cb->fillMode, TRUE) || + !read_order_field_color(orderInfo, s, 5, &polygon_cb->backColor, TRUE) || + !read_order_field_color(orderInfo, s, 6, &polygon_cb->foreColor, TRUE)) + return FALSE; if (!update_read_brush(s, &polygon_cb->brush, orderInfo->fieldFlags >> 6)) return FALSE; - ORDER_FIELD_BYTE(12, num); + if (!read_order_field_byte(orderInfo, s, 12, &num, TRUE)) + return FALSE; - if (orderInfo->fieldFlags & ORDER_FIELD_13) + if ((orderInfo->fieldFlags & ORDER_FIELD_13) != 0) { DELTA_POINT* newpoints; @@ -1951,27 +1987,30 @@ static BOOL update_read_ellipse_sc_order(wStream* s, const ORDER_INFO* orderInfo, ELLIPSE_SC_ORDER* ellipse_sc) { - ORDER_FIELD_COORD(1, ellipse_sc->leftRect); - ORDER_FIELD_COORD(2, ellipse_sc->topRect); - ORDER_FIELD_COORD(3, ellipse_sc->rightRect); - ORDER_FIELD_COORD(4, ellipse_sc->bottomRect); - ORDER_FIELD_BYTE(5, ellipse_sc->bRop2); - ORDER_FIELD_BYTE(6, ellipse_sc->fillMode); - ORDER_FIELD_COLOR(orderInfo, s, 7, &ellipse_sc->color); - return TRUE; + if (read_order_field_coord(orderInfo, s, 1, &ellipse_sc->leftRect, FALSE) && + read_order_field_coord(orderInfo, s, 2, &ellipse_sc->topRect, FALSE) && + read_order_field_coord(orderInfo, s, 3, &ellipse_sc->rightRect, FALSE) && + read_order_field_coord(orderInfo, s, 4, &ellipse_sc->bottomRect, FALSE) && + read_order_field_byte(orderInfo, s, 5, &ellipse_sc->bRop2, TRUE) && + read_order_field_byte(orderInfo, s, 6, &ellipse_sc->fillMode, TRUE) && + read_order_field_color(orderInfo, s, 7, &ellipse_sc->color, TRUE)) + return TRUE; + return FALSE; } static BOOL update_read_ellipse_cb_order(wStream* s, const ORDER_INFO* orderInfo, ELLIPSE_CB_ORDER* ellipse_cb) { - ORDER_FIELD_COORD(1, ellipse_cb->leftRect); - ORDER_FIELD_COORD(2, ellipse_cb->topRect); - ORDER_FIELD_COORD(3, ellipse_cb->rightRect); - ORDER_FIELD_COORD(4, ellipse_cb->bottomRect); - ORDER_FIELD_BYTE(5, ellipse_cb->bRop2); - ORDER_FIELD_BYTE(6, ellipse_cb->fillMode); - ORDER_FIELD_COLOR(orderInfo, s, 7, &ellipse_cb->backColor); - ORDER_FIELD_COLOR(orderInfo, s, 8, &ellipse_cb->foreColor); - return update_read_brush(s, &ellipse_cb->brush, orderInfo->fieldFlags >> 8); + if (read_order_field_coord(orderInfo, s, 1, &ellipse_cb->leftRect, FALSE) && + read_order_field_coord(orderInfo, s, 2, &ellipse_cb->topRect, FALSE) && + read_order_field_coord(orderInfo, s, 3, &ellipse_cb->rightRect, FALSE) && + read_order_field_coord(orderInfo, s, 4, &ellipse_cb->bottomRect, FALSE) && + read_order_field_byte(orderInfo, s, 5, &ellipse_cb->bRop2, TRUE) && + read_order_field_byte(orderInfo, s, 6, &ellipse_cb->fillMode, TRUE) && + read_order_field_color(orderInfo, s, 7, &ellipse_cb->backColor, TRUE) && + read_order_field_color(orderInfo, s, 8, &ellipse_cb->foreColor, TRUE) && + update_read_brush(s, &ellipse_cb->brush, orderInfo->fieldFlags >> 8)) + return TRUE; + return FALSE; } /* Secondary Drawing Orders */ static CACHE_BITMAP_ORDER* update_read_cache_bitmap_order(rdpUpdate* update, wStream* s, @@ -2618,10 +2657,11 @@ } static BOOL update_decompress_brush(wStream* s, BYTE* output, size_t outSize, BYTE bpp) { - INT32 x, y, k; + size_t x, k; + INT8 y; BYTE byte = 0; const BYTE* palette = Stream_Pointer(s) + 16; - const INT32 bytesPerPixel = ((bpp + 1) / 8); + const size_t bytesPerPixel = ((bpp + 1) / 8); if (Stream_GetRemainingLength(s) < 16 + bytesPerPixel * 4) return FALSE; @@ -2676,6 +2716,8 @@ Stream_Read_UINT8(s, cache_brush->cx); /* cx (1 byte) */ Stream_Read_UINT8(s, cache_brush->cy); /* cy (1 byte) */ + /* according to Section 2.2.2.2.1.2.7 errata the windows implementation sets this filed is set + * to 0x00 */ Stream_Read_UINT8(s, cache_brush->style); /* style (1 byte) */ Stream_Read_UINT8(s, cache_brush->length); /* iBytes (1 byte) */ @@ -2690,14 +2732,12 @@ goto fail; } - /* rows are encoded in reverse order */ if (Stream_GetRemainingLength(s) < 8) goto fail; + /* rows are encoded in reverse order */ for (i = 7; i >= 0; i--) - { Stream_Read_UINT8(s, cache_brush->data[i]); - } } else { @@ -2705,6 +2745,8 @@ compressed = TRUE; else if ((iBitmapFormat == BMF_16BPP) && (cache_brush->length == 24)) compressed = TRUE; + else if ((iBitmapFormat == BMF_24BPP) && (cache_brush->length == 28)) + compressed = TRUE; else if ((iBitmapFormat == BMF_32BPP) && (cache_brush->length == 32)) compressed = TRUE; @@ -3385,6 +3427,7 @@ } orderName = primary_order_string(orderInfo->orderType); + WLog_Print(update->log, WLOG_DEBUG, "Primary Drawing Order %s", orderName); if (!check_primary_order_supported(update->log, settings, orderInfo->orderType, orderName)) return FALSE; @@ -3421,6 +3464,10 @@ if (!read_primary_order(update->log, orderName, s, orderInfo, primary)) return FALSE; + rc = IFCALLRESULT(TRUE, primary->OrderInfo, context, orderInfo, orderName); + if (!rc) + return FALSE; + switch (orderInfo->orderType) { case ORDER_TYPE_DSTBLT: @@ -3635,6 +3682,19 @@ Stream_Read_UINT16(s, orderLength); /* orderLength (2 bytes) */ Stream_Read_UINT16(s, extraFlags); /* extraFlags (2 bytes) */ Stream_Read_UINT8(s, orderType); /* orderType (1 byte) */ + + start = Stream_GetPosition(s); + name = secondary_order_string(orderType); + WLog_Print(update->log, WLOG_DEBUG, "Secondary Drawing Order %s", name); + rc = IFCALLRESULT(TRUE, secondary->CacheOrderInfo, context, orderLength, extraFlags, orderType, + name); + if (!rc) + return FALSE; + + /* + * According to [MS-RDPEGDI] 2.2.2.2.1.2.1.1 the order length must be increased by 13 bytes + * including the header. As we already read the header 7 left + */ if (Stream_GetRemainingLength(s) < orderLength + 7U) { WLog_Print(update->log, WLOG_ERROR, "Stream_GetRemainingLength(s) %" PRIuz " < %" PRIu16, @@ -3642,10 +3702,6 @@ return FALSE; } - start = Stream_GetPosition(s); - name = secondary_order_string(orderType); - WLog_Print(update->log, WLOG_DEBUG, "Secondary Drawing Order %s", name); - if (!check_secondary_order_supported(update->log, settings, orderType, name)) return FALSE; @@ -3865,6 +3921,10 @@ const char* orderName = altsec_order_string(orderType); WLog_Print(update->log, WLOG_DEBUG, "Alternate Secondary Drawing Order %s", orderName); + rc = IFCALLRESULT(TRUE, altsec->DrawOrderInfo, context, orderType, orderName); + if (!rc) + return FALSE; + if (!check_alt_order_supported(update->log, settings, orderType, orderName)) return FALSE; diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/peer.c freerdp2-2.3.0+dfsg1/libfreerdp/core/peer.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/peer.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/peer.c 2021-02-25 08:51:41.000000000 +0000 @@ -276,8 +276,7 @@ #ifdef WITH_DEBUG_RDP WLog_DBG(TAG, "recv %s Data PDU (0x%02" PRIX8 "), length: %" PRIu16 "", - type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, - length); + data_pdu_type_to_string(type), type, length); #endif switch (type) @@ -301,7 +300,8 @@ break; case DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST: - /* TODO: notify server bitmap cache data */ + if (!rdp_server_accept_client_persistent_key_list_pdu(client->context->rdp, s)) + return FALSE; break; case DATA_PDU_TYPE_FONT_LIST: @@ -386,6 +386,7 @@ client->settings->PduSource = pduSource; + WLog_DBG(TAG, "Received %s", pdu_type_to_str(pduType)); switch (pduType) { case PDU_TYPE_DATA: @@ -425,9 +426,9 @@ if (!freerdp_channel_peer_process(client, s, channelId)) return -1; } - if (!tpkt_ensure_stream_consumed(s, length)) return -1; + return 0; } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/proxy.c freerdp2-2.3.0+dfsg1/libfreerdp/core/proxy.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/proxy.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/proxy.c 2021-02-25 08:51:41.000000000 +0000 @@ -71,28 +71,28 @@ BOOL proxy_prepare(rdpSettings* settings, const char** lpPeerHostname, UINT16* lpPeerPort, const char** lpProxyUsername, const char** lpProxyPassword) { - if (settings->ProxyType == PROXY_TYPE_IGNORE) + if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) == PROXY_TYPE_IGNORE) return FALSE; /* For TSGateway, find the system HTTPS proxy automatically */ - if (settings->ProxyType == PROXY_TYPE_NONE) + if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) == PROXY_TYPE_NONE) proxy_read_environment(settings, "https_proxy"); - if (settings->ProxyType == PROXY_TYPE_NONE) + if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) == PROXY_TYPE_NONE) proxy_read_environment(settings, "HTTPS_PROXY"); - if (settings->ProxyType != PROXY_TYPE_NONE) + if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) != PROXY_TYPE_NONE) proxy_read_environment(settings, "no_proxy"); - if (settings->ProxyType != PROXY_TYPE_NONE) + if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) != PROXY_TYPE_NONE) proxy_read_environment(settings, "NO_PROXY"); - if (settings->ProxyType != PROXY_TYPE_NONE) + if (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType) != PROXY_TYPE_NONE) { - *lpPeerHostname = settings->ProxyHostname; - *lpPeerPort = settings->ProxyPort; - *lpProxyUsername = settings->ProxyUsername; - *lpProxyPassword = settings->ProxyPassword; + *lpPeerHostname = freerdp_settings_get_string(settings, FreeRDP_ProxyHostname); + *lpPeerPort = freerdp_settings_get_uint16(settings, FreeRDP_ProxyPort); + *lpProxyUsername = freerdp_settings_get_string(settings, FreeRDP_ProxyUsername); + *lpProxyPassword = freerdp_settings_get_string(settings, FreeRDP_ProxyPassword); return TRUE; } @@ -274,9 +274,10 @@ { if (check_no_proxy(settings, env)) { - WLog_INFO(TAG, "deactivating proxy: %s [%s=%s]", settings->ServerHostname, envname, + WLog_INFO(TAG, "deactivating proxy: %s [%s=%s]", + freerdp_settings_get_string(settings, FreeRDP_ServerHostname), envname, env); - settings->ProxyType = PROXY_TYPE_NONE; + freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_NONE); } } else @@ -288,31 +289,38 @@ free(env); } -BOOL proxy_parse_uri(rdpSettings* settings, const char* uri) +BOOL proxy_parse_uri(rdpSettings* settings, const char* uri_in) { - const char *hostname, *pport; + BOOL rc = FALSE; + char *hostname, *pport; const char* protocol; - const char* p; + char* p; UINT16 port; - int hostnamelen; + char* uri_copy = _strdup(uri_in); + char* uri = uri_copy; + if (!uri) + return FALSE; p = strstr(uri, "://"); if (p) { if (p == uri + 4 && !strncmp("http", uri, 4)) { - settings->ProxyType = PROXY_TYPE_HTTP; + if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_HTTP)) + goto fail; + protocol = "http"; } else if (p == uri + 6 && !strncmp("socks5", uri, 6)) { - settings->ProxyType = PROXY_TYPE_SOCKS; + if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_SOCKS)) + goto fail; protocol = "socks5"; } else { WLog_ERR(TAG, "Only HTTP and SOCKS5 proxies supported by now"); - return FALSE; + goto fail; } uri = p + 3; @@ -320,7 +328,7 @@ else { WLog_ERR(TAG, "No scheme in proxy URI"); - return FALSE; + goto fail; } hostname = uri; @@ -345,33 +353,28 @@ } if (pport) - { - hostnamelen = pport - hostname; - } - else - { - hostnamelen = strlen(hostname); - } + *pport = '\0'; - settings->ProxyHostname = calloc(hostnamelen + 1, 1); + if (!freerdp_settings_set_string(settings, FreeRDP_ProxyHostname, hostname)) + goto fail; - if (!settings->ProxyHostname) - { - WLog_ERR(TAG, "Not enough memory"); - return FALSE; - } + if (!freerdp_settings_set_uint16(settings, FreeRDP_ProxyPort, port)) + goto fail; - memcpy(settings->ProxyHostname, hostname, hostnamelen); - settings->ProxyPort = port; - WLog_INFO(TAG, "Parsed proxy configuration: %s://%s:%d", protocol, settings->ProxyHostname, - settings->ProxyPort); - return TRUE; + WLog_INFO(TAG, "Parsed proxy configuration: %s://%s:%d", protocol, + freerdp_settings_get_string(settings, FreeRDP_ProxyHostname), + freerdp_settings_get_uint16(settings, FreeRDP_ProxyPort)); + rc = TRUE; + +fail: + free(uri_copy); + return rc; } BOOL proxy_connect(rdpSettings* settings, BIO* bufferedBio, const char* proxyUsername, const char* proxyPassword, const char* hostname, UINT16 port) { - switch (settings->ProxyType) + switch (freerdp_settings_get_uint32(settings, FreeRDP_ProxyType)) { case PROXY_TYPE_NONE: case PROXY_TYPE_IGNORE: diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/rdp.c freerdp2-2.3.0+dfsg1/libfreerdp/core/rdp.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/rdp.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/rdp.c 2021-02-25 08:51:41.000000000 +0000 @@ -34,7 +34,7 @@ #define TAG FREERDP_TAG("core.rdp") -const char* DATA_PDU_TYPE_STRINGS[80] = { +static const char* DATA_PDU_TYPE_STRINGS[80] = { "?", "?", /* 0x00 - 0x01 */ "Update", /* 0x02 */ @@ -102,10 +102,17 @@ "?" /* 0x41 - 0x46 */ }; +const char* data_pdu_type_to_string(UINT8 type) +{ + if (type > ARRAYSIZE(DATA_PDU_TYPE_STRINGS)) + return "???"; + return DATA_PDU_TYPE_STRINGS[type]; +} + static BOOL rdp_read_flow_control_pdu(wStream* s, UINT16* type, UINT16* channel_id); -static void rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type, +static BOOL rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type, UINT16 channel_id); -static void rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 share_id); +static BOOL rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 share_id); /** * Read RDP Security Header.\n @@ -192,13 +199,18 @@ return TRUE; } -void rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type, UINT16 channel_id) +BOOL rdp_write_share_control_header(wStream* s, UINT16 length, UINT16 type, UINT16 channel_id) { + if (length < RDP_PACKET_HEADER_MAX_LENGTH) + return FALSE; + if (Stream_GetRemainingCapacity(s) < 6) + return FALSE; length -= RDP_PACKET_HEADER_MAX_LENGTH; /* Share Control Header */ Stream_Write_UINT16(s, length); /* totalLength */ Stream_Write_UINT16(s, type | 0x10); /* pduType */ Stream_Write_UINT16(s, channel_id); /* pduSource */ + return TRUE; } BOOL rdp_read_share_data_header(wStream* s, UINT16* length, BYTE* type, UINT32* shareId, @@ -218,11 +230,16 @@ return TRUE; } -void rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 share_id) +BOOL rdp_write_share_data_header(wStream* s, UINT16 length, BYTE type, UINT32 share_id) { - length -= RDP_PACKET_HEADER_MAX_LENGTH; - length -= RDP_SHARE_CONTROL_HEADER_LENGTH; - length -= RDP_SHARE_DATA_HEADER_LENGTH; + const size_t headerLen = RDP_PACKET_HEADER_MAX_LENGTH + RDP_SHARE_CONTROL_HEADER_LENGTH + + RDP_SHARE_DATA_HEADER_LENGTH; + if (length < headerLen) + return FALSE; + length -= headerLen; + if (Stream_GetRemainingCapacity(s) < 12) + return FALSE; + /* Share Data Header */ Stream_Write_UINT32(s, share_id); /* shareId (4 bytes) */ Stream_Write_UINT8(s, 0); /* pad1 (1 byte) */ @@ -231,6 +248,7 @@ Stream_Write_UINT8(s, type); /* pduType2, Data PDU Type (1 byte) */ Stream_Write_UINT8(s, 0); /* compressedType (1 byte) */ Stream_Write_UINT16(s, 0); /* compressedLength (2 bytes) */ + return TRUE; } static BOOL rdp_security_stream_init(rdpRdp* rdp, wStream* s, BOOL sec_header) @@ -662,7 +680,8 @@ sec_bytes = rdp_get_sec_bytes(rdp, 0); sec_hold = Stream_GetPosition(s); Stream_Seek(s, sec_bytes); - rdp_write_share_control_header(s, length - sec_bytes, type, channel_id); + if (!rdp_write_share_control_header(s, length - sec_bytes, type, channel_id)) + return FALSE; Stream_SetPosition(s, sec_hold); if (!rdp_security_stream_out(rdp, s, length, 0, &pad)) @@ -698,8 +717,10 @@ sec_bytes = rdp_get_sec_bytes(rdp, 0); sec_hold = Stream_GetPosition(s); Stream_Seek(s, sec_bytes); - rdp_write_share_control_header(s, length - sec_bytes, PDU_TYPE_DATA, channel_id); - rdp_write_share_data_header(s, length - sec_bytes, type, rdp->settings->ShareId); + if (!rdp_write_share_control_header(s, length - sec_bytes, PDU_TYPE_DATA, channel_id)) + goto fail; + if (!rdp_write_share_data_header(s, length - sec_bytes, type, rdp->settings->ShareId)) + goto fail; Stream_SetPosition(s, sec_hold); if (!rdp_security_stream_out(rdp, s, length, 0, &pad)) @@ -920,8 +941,7 @@ } WLog_DBG(TAG, "recv %s Data PDU (0x%02" PRIX8 "), length: %" PRIu16 "", - type < ARRAYSIZE(DATA_PDU_TYPE_STRINGS) ? DATA_PDU_TYPE_STRINGS[type] : "???", type, - length); + data_pdu_type_to_string(type), type, length); switch (type) { @@ -1250,7 +1270,7 @@ return TRUE; } -static const char* pdu_type_to_str(UINT16 pduType) +const char* pdu_type_to_str(UINT16 pduType) { static char buffer[1024] = { 0 }; switch (pduType) @@ -1628,12 +1648,7 @@ if ((status >= 0) && (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE)) { - ActivatedEventArgs activatedEvent; - rdpContext* context = rdp->context; rdp_client_transition_to_state(rdp, CONNECTION_STATE_ACTIVE); - EventArgsInit(&activatedEvent, "libfreerdp"); - activatedEvent.firstActivation = !rdp->deactivation_reactivation; - PubSub_OnActivated(context->pubSub, context, &activatedEvent); return 2; } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/rdp.h freerdp2-2.3.0+dfsg1/libfreerdp/core/rdp.h --- freerdp2-2.2.0+dfsg1/libfreerdp/core/rdp.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/rdp.h 2021-02-25 08:51:41.000000000 +0000 @@ -227,7 +227,6 @@ #define RDP_TAG FREERDP_TAG("core.rdp") #ifdef WITH_DEBUG_RDP #define DEBUG_RDP(...) WLog_DBG(RDP_TAG, __VA_ARGS__) -extern const char* DATA_PDU_TYPE_STRINGS[80]; #else #define DEBUG_RDP(...) \ do \ @@ -235,6 +234,9 @@ } while (0) #endif +const char* data_pdu_type_to_string(UINT8 type); +const char* pdu_type_to_str(UINT16 pduType); + BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags); BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo); diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/settings.c freerdp2-2.3.0+dfsg1/libfreerdp/core/settings.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/settings.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/settings.c 2021-02-25 08:51:41.000000000 +0000 @@ -244,32 +244,16 @@ static BOOL settings_get_computer_name(rdpSettings* settings) { - DWORD nSize = 0; - CHAR* computerName; - - if (GetComputerNameExA(ComputerNameNetBIOS, NULL, &nSize) || GetLastError() != ERROR_MORE_DATA) - return FALSE; - - computerName = calloc(nSize, sizeof(CHAR)); - - if (!computerName) - return FALSE; + CHAR computerName[256]; + DWORD nSize = sizeof(computerName); if (!GetComputerNameExA(ComputerNameNetBIOS, computerName, &nSize)) - { - free(computerName); return FALSE; - } if (nSize > MAX_COMPUTERNAME_LENGTH) computerName[MAX_COMPUTERNAME_LENGTH] = '\0'; - settings->ComputerName = computerName; - - if (!settings->ComputerName) - return FALSE; - - return TRUE; + return freerdp_settings_set_string(settings, FreeRDP_ComputerName, computerName); } BOOL freerdp_settings_set_default_order_support(rdpSettings* settings) @@ -367,6 +351,7 @@ settings->DisableMenuAnims = TRUE; settings->DisableThemes = FALSE; settings->ConnectionType = CONNECTION_TYPE_LAN; + settings->NetworkAutoDetect = TRUE; settings->EncryptionMethods = ENCRYPTION_METHOD_NONE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; settings->FIPSMode = FALSE; @@ -436,7 +421,7 @@ settings->AllowCacheWaitingList = TRUE; settings->BitmapCacheV2NumCells = 5; settings->BitmapCacheV2CellInfo = - (BITMAP_CACHE_V2_CELL_INFO*)malloc(sizeof(BITMAP_CACHE_V2_CELL_INFO) * 6); + (BITMAP_CACHE_V2_CELL_INFO*)calloc(6, sizeof(BITMAP_CACHE_V2_CELL_INFO)); if (!settings->BitmapCacheV2CellInfo) goto out_fail; @@ -455,12 +440,12 @@ settings->RefreshRect = TRUE; settings->SuppressOutput = TRUE; settings->GlyphSupportLevel = GLYPH_SUPPORT_NONE; - settings->GlyphCache = malloc(sizeof(GLYPH_CACHE_DEFINITION) * 10); + settings->GlyphCache = calloc(10, sizeof(GLYPH_CACHE_DEFINITION)); if (!settings->GlyphCache) goto out_fail; - settings->FragCache = malloc(sizeof(GLYPH_CACHE_DEFINITION)); + settings->FragCache = calloc(1, sizeof(GLYPH_CACHE_DEFINITION)); if (!settings->FragCache) goto out_fail; @@ -543,21 +528,21 @@ settings->DeviceArraySize = 16; settings->DeviceArray = - (RDPDR_DEVICE**)calloc(1, sizeof(RDPDR_DEVICE*) * settings->DeviceArraySize); + (RDPDR_DEVICE**)calloc(settings->DeviceArraySize, sizeof(RDPDR_DEVICE*)); if (!settings->DeviceArray) goto out_fail; settings->StaticChannelArraySize = 16; settings->StaticChannelArray = - (ADDIN_ARGV**)calloc(1, sizeof(ADDIN_ARGV*) * settings->StaticChannelArraySize); + (ADDIN_ARGV**)calloc(settings->StaticChannelArraySize, sizeof(ADDIN_ARGV*)); if (!settings->StaticChannelArray) goto out_fail; settings->DynamicChannelArraySize = 16; settings->DynamicChannelArray = - (ADDIN_ARGV**)calloc(1, sizeof(ADDIN_ARGV*) * settings->DynamicChannelArraySize); + (ADDIN_ARGV**)calloc(settings->DynamicChannelArraySize, sizeof(ADDIN_ARGV*)); if (!settings->DynamicChannelArray) goto out_fail; @@ -610,6 +595,7 @@ settings_load_hkey_local_machine(settings); settings->ActionScript = _strdup("~/.config/freerdp/action.sh"); + settings->XSelectionAtom = NULL; settings->SmartcardLogon = FALSE; settings->TlsSecLevel = 1; settings->OrderSupport = calloc(1, 32); @@ -656,6 +642,8 @@ /* Extensions */ free(settings->ActionScript); settings->ActionScript = NULL; + free(settings->XSelectionAtom); + settings->XSelectionAtom = NULL; /* Free all strings, set other pointers NULL */ freerdp_settings_free_keys(settings, TRUE); @@ -697,7 +685,7 @@ if (!_settings->ServerRandom) goto out_fail; - CopyMemory(_settings->ServerRandom, settings->ServerRandom, _settings->ServerRandomLength); + CopyMemory(_settings->ServerRandom, settings->ServerRandom, settings->ServerRandomLength); _settings->ServerRandomLength = settings->ServerRandomLength; } @@ -708,10 +696,22 @@ if (!_settings->ClientRandom) goto out_fail; - CopyMemory(_settings->ClientRandom, settings->ClientRandom, _settings->ClientRandomLength); + CopyMemory(_settings->ClientRandom, settings->ClientRandom, settings->ClientRandomLength); _settings->ClientRandomLength = settings->ClientRandomLength; } + if (settings->ServerCertificateLength) + { + _settings->ServerCertificate = (BYTE*)malloc(settings->ServerCertificateLength); + + if (!_settings->ServerCertificate) + goto out_fail; + + CopyMemory(_settings->ServerCertificate, settings->ServerCertificate, + settings->ServerCertificateLength); + _settings->ServerCertificateLength = settings->ServerCertificateLength; + } + if (settings->RdpServerCertificate) { _settings->RdpServerCertificate = certificate_clone(settings->RdpServerCertificate); @@ -983,6 +983,8 @@ if (settings->ActionScript) _settings->ActionScript = _strdup(settings->ActionScript); + if (settings->XSelectionAtom) + _settings->XSelectionAtom = _strdup(settings->XSelectionAtom); rc = TRUE; out_fail: return rc; @@ -1024,6 +1026,7 @@ _settings->StaticChannelArray = NULL; _settings->DynamicChannelArray = NULL; _settings->ActionScript = NULL; + _settings->XSelectionAtom = NULL; if (!rc) goto out_fail; diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/test/settings_property_lists.h freerdp2-2.3.0+dfsg1/libfreerdp/core/test/settings_property_lists.h --- freerdp2-2.2.0+dfsg1/libfreerdp/core/test/settings_property_lists.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/test/settings_property_lists.h 2021-02-25 08:51:41.000000000 +0000 @@ -333,6 +333,7 @@ FreeRDP_ImeFileName, FreeRDP_KerberosKdc, FreeRDP_KerberosRealm, + FreeRDP_KeyboardRemappingList, FreeRDP_NtlmSamFile, FreeRDP_Password, FreeRDP_PasswordHash, diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/tpkt.c freerdp2-2.3.0+dfsg1/libfreerdp/core/tpkt.c --- freerdp2-2.2.0+dfsg1/libfreerdp/core/tpkt.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/tpkt.c 2021-02-25 08:51:41.000000000 +0000 @@ -148,9 +148,12 @@ * @param length */ -void tpkt_write_header(wStream* s, UINT16 length) +BOOL tpkt_write_header(wStream* s, UINT16 length) { + if (Stream_GetRemainingCapacity(s) < 4) + return FALSE; Stream_Write_UINT8(s, 3); /* version */ Stream_Write_UINT8(s, 0); /* reserved */ Stream_Write_UINT16_BE(s, length); /* length */ + return TRUE; } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/core/tpkt.h freerdp2-2.3.0+dfsg1/libfreerdp/core/tpkt.h --- freerdp2-2.2.0+dfsg1/libfreerdp/core/tpkt.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/core/tpkt.h 2021-02-25 08:51:41.000000000 +0000 @@ -30,7 +30,7 @@ FREERDP_LOCAL BOOL tpkt_verify_header(wStream* s); FREERDP_LOCAL BOOL tpkt_read_header(wStream* s, UINT16* length); -FREERDP_LOCAL void tpkt_write_header(wStream* s, UINT16 length); +FREERDP_LOCAL BOOL tpkt_write_header(wStream* s, UINT16 length); #define tpkt_ensure_stream_consumed(s, length) \ tpkt_ensure_stream_consumed_((s), (length), __FUNCTION__) FREERDP_LOCAL BOOL tpkt_ensure_stream_consumed_(wStream* s, UINT16 length, const char* fkt); diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/crypto/crypto.c freerdp2-2.3.0+dfsg1/libfreerdp/crypto/crypto.c --- freerdp2-2.2.0+dfsg1/libfreerdp/crypto/crypto.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/crypto/crypto.c 2021-02-25 08:51:41.000000000 +0000 @@ -110,15 +110,15 @@ if (!input || (length < 0) || (exponent_size < 0) || !modulus || !exponent || !output) return -1; - if (exponent_size > SIZE_MAX / 2) + if ((size_t)exponent_size > SIZE_MAX / 2) return -1; if (key_length >= SIZE_MAX / 2 - exponent_size) return -1; bufferSize = 2ULL * key_length + exponent_size; - if (length > bufferSize) - bufferSize = length; + if ((size_t)length > bufferSize) + bufferSize = (size_t)length; input_reverse = (BYTE*)calloc(bufferSize, 1); @@ -163,7 +163,7 @@ goto fail; crypto_reverse(output, output_length); - if (output_length < key_length) + if ((UINT32)output_length < key_length) memset(output + output_length, 0, key_length - output_length); fail: diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/crypto/test/CMakeLists.txt freerdp2-2.3.0+dfsg1/libfreerdp/crypto/test/CMakeLists.txt --- freerdp2-2.2.0+dfsg1/libfreerdp/crypto/test/CMakeLists.txt 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/crypto/test/CMakeLists.txt 2021-02-25 08:51:41.000000000 +0000 @@ -17,6 +17,10 @@ add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) +file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} TEST_PATH) +string(REGEX REPLACE "\\\\" "\\\\\\\\" TEST_PATH ${TEST_PATH}) + +add_definitions(-DTEST_SOURCE_DIR="${TEST_PATH}") target_link_libraries(${MODULE_NAME} freerdp winpr ${OPENSSL_LIBRARIES}) set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}") diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/crypto/test/Test_x509_cert_info.c freerdp2-2.3.0+dfsg1/libfreerdp/crypto/test/Test_x509_cert_info.c --- freerdp2-2.2.0+dfsg1/libfreerdp/crypto/test/Test_x509_cert_info.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/crypto/test/Test_x509_cert_info.c 2021-02-25 08:51:41.000000000 +0000 @@ -33,6 +33,15 @@ static const char dirsep = '/'; #endif static const char filename[] = "Test_x509_cert_info.pem"; +#ifdef TEST_SOURCE_DIR + const char* file = TEST_SOURCE_DIR; + const size_t flen = sizeof(filename) + sizeof(dirsep) + strlen(file) + sizeof(char); + char* result = calloc(1, flen); + if (!result) + return NULL; + _snprintf(result, flen - 1, "%s%c%s", file, dirsep, filename); + return result; +#else const char* file = __FILE__; const char* last_dirsep = strrchr(file, dirsep); @@ -52,6 +61,7 @@ /* No dirsep => relative path in same directory */ return _strdup(filename); } +#endif } static const certificate_test_t certificate_tests[] = { diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/crypto/tls.c freerdp2-2.3.0+dfsg1/libfreerdp/crypto/tls.c --- freerdp2-2.2.0+dfsg1/libfreerdp/crypto/tls.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/crypto/tls.c 2021-02-25 08:51:41.000000000 +0000 @@ -461,6 +461,7 @@ if (!tls) return 0; + BIO_set_data(bio, NULL); if (BIO_get_shutdown(bio)) { if (BIO_get_init(bio) && tls->ssl) @@ -475,6 +476,7 @@ DeleteCriticalSection(&tls->lock); free(tls); + return 1; } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/gdi/gfx.c freerdp2-2.3.0+dfsg1/libfreerdp/gdi/gfx.c --- freerdp2-2.2.0+dfsg1/libfreerdp/gdi/gfx.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/gdi/gfx.c 2021-02-25 08:51:41.000000000 +0000 @@ -221,6 +221,7 @@ { rdpGdi* gdi = (rdpGdi*)context->custom; gdi->inGfxFrame = TRUE; + gdi->frameId = startFrame->frameId; return CHANNEL_RC_OK; } @@ -824,13 +825,13 @@ } region16_init(&invalidRegion); - rc = progressive_decompress(surface->codecs->progressive, cmd->data, cmd->length, surface->data, - surface->format, surface->scanline, cmd->left, cmd->top, - &invalidRegion, cmd->surfaceId); + rc = progressive_decompress_ex(surface->codecs->progressive, cmd->data, cmd->length, + surface->data, surface->format, surface->scanline, cmd->left, + cmd->top, &invalidRegion, cmd->surfaceId, gdi->frameId); if (rc < 0) { - WLog_ERR(TAG, "progressive_decompress failure: %" PRId32 "", rc); + WLog_ERR(TAG, "progressive_decompress_ex failure: %" PRId32 "", rc); region16_uninit(&invalidRegion); return ERROR_INTERNAL_ERROR; } @@ -1468,9 +1469,13 @@ pcRdpgfxUnmapWindowForSurface unmap, pcRdpgfxUpdateSurfaceArea update) { - if (!gdi || !gfx) + rdpContext* context; + + if (!gdi || !gfx || !gdi->context || !gdi->context->settings) return FALSE; + context = gdi->context; + gdi->gfx = gfx; gfx->custom = (void*)gdi; gfx->ResetGraphics = gdi_ResetGraphics; diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/gdi/graphics.c freerdp2-2.3.0+dfsg1/libfreerdp/gdi/graphics.c --- freerdp2-2.2.0+dfsg1/libfreerdp/gdi/graphics.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/gdi/graphics.c 2021-02-25 08:51:41.000000000 +0000 @@ -162,6 +162,8 @@ } else { + freerdp_planar_switch_bgr(context->codecs->planar, + context->settings->DrawAllowDynamicColorFidelity); if (!planar_decompress(context->codecs->planar, pSrcData, SrcSize, DstWidth, DstHeight, bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight, TRUE)) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/locale/keyboard.c freerdp2-2.3.0+dfsg1/libfreerdp/locale/keyboard.c --- freerdp2-2.2.0+dfsg1/libfreerdp/locale/keyboard.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/locale/keyboard.c 2021-02-25 08:51:41.000000000 +0000 @@ -42,11 +42,28 @@ #endif -DWORD VIRTUAL_SCANCODE_TO_X11_KEYCODE[256][2]; -DWORD X11_KEYCODE_TO_VIRTUAL_SCANCODE[256]; +static DWORD VIRTUAL_SCANCODE_TO_X11_KEYCODE[256][2] = { 0 }; +static DWORD X11_KEYCODE_TO_VIRTUAL_SCANCODE[256] = { 0 }; +static DWORD REMAPPING_TABLE[0x10000] = { 0 }; int freerdp_detect_keyboard(DWORD* keyboardLayoutId) { +#if defined(_WIN32) + CHAR name[KL_NAMELENGTH + 1] = { 0 }; + if (GetKeyboardLayoutNameA(name)) + { + ULONG rc; + + errno = 0; + rc = strtoul(name, NULL, 16); + if (errno == 0) + *keyboardLayoutId = rc; + } + + if (*keyboardLayoutId == 0) + *keyboardLayoutId = ((DWORD)GetKeyboardLayout(0) >> 16) & 0x0000FFFF; +#endif + #ifdef WITH_X11 if (*keyboardLayoutId == 0) freerdp_detect_keyboard_layout_from_xkb(keyboardLayoutId); @@ -138,13 +155,60 @@ return keyboardLayoutId; } +DWORD freerdp_keyboard_init_ex(DWORD keyboardLayoutId, const char* keyboardRemappingList) +{ + DWORD rc = freerdp_keyboard_init(keyboardLayoutId); + + memset(REMAPPING_TABLE, 0, sizeof(REMAPPING_TABLE)); + if (keyboardRemappingList) + { + char* copy = _strdup(keyboardRemappingList); + char* context = NULL; + char* token; + if (!copy) + goto fail; + token = strtok_s(copy, ",", &context); + while (token) + { + DWORD key, value; + int rc = sscanf(token, "%" PRIu32 "=%" PRIu32, &key, &value); + if (rc != 2) + rc = sscanf(token, "%" PRIx32 "=%" PRIx32 "", &key, &value); + if (rc != 2) + rc = sscanf(token, "%" PRIu32 "=%" PRIx32, &key, &value); + if (rc != 2) + rc = sscanf(token, "%" PRIx32 "=%" PRIu32, &key, &value); + if (rc != 2) + goto fail; + if (key >= ARRAYSIZE(REMAPPING_TABLE)) + goto fail; + REMAPPING_TABLE[key] = value; + token = strtok_s(NULL, ",", &context); + } + fail: + free(copy); + } + return rc; +} + DWORD freerdp_keyboard_get_rdp_scancode_from_x11_keycode(DWORD keycode) { - DEBUG_KBD("x11 keycode: %02" PRIX32 " -> rdp code: %02" PRIX8 "%s", keycode, - RDP_SCANCODE_CODE(X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode]), - RDP_SCANCODE_EXTENDED(X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode]) ? " extended" : ""); + const DWORD scancode = X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode]; + const DWORD remapped = REMAPPING_TABLE[scancode]; + DEBUG_KBD("x11 keycode: %02" PRIX32 " -> rdp code: [%04" PRIx16 "] %02" PRIX8 "%s", keycode, + scancode, RDP_SCANCODE_CODE(scancode), + RDP_SCANCODE_EXTENDED(scancode) ? " extended" : ""); - return X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode]; + if (remapped != 0) + { + DEBUG_KBD("remapped scancode: [%04" PRIx16 "] %02" PRIX8 "[%s] -> [%04" PRIx16 "] %02" PRIX8 + "[%s]", + scancode, RDP_SCANCODE_CODE(scancode), + RDP_SCANCODE_EXTENDED(scancode) ? " extended" : "", remapped, + RDP_SCANCODE_CODE(remapped), RDP_SCANCODE_EXTENDED(remapped) ? " extended" : ""); + return remapped; + } + return scancode; } DWORD freerdp_keyboard_get_x11_keycode_from_rdp_scancode(DWORD scancode, BOOL extended) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/locale/keyboard_x11.c freerdp2-2.3.0+dfsg1/libfreerdp/locale/keyboard_x11.c --- freerdp2-2.2.0+dfsg1/libfreerdp/locale/keyboard_x11.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/locale/keyboard_x11.c 2021-02-25 08:51:41.000000000 +0000 @@ -80,6 +80,11 @@ layout = beg; + /* if multiple languages are present we just take the first one */ + pch = strchr(layout, ','); + if (pch) + *pch = '\0'; + /* "variant" */ beg = strchr(end + 1, '"'); beg += 1; @@ -124,6 +129,11 @@ layout = beg; + /* if multiple languages are present we just take the first one */ + pch = strchr(layout, ','); + if (pch) + *pch = '\0'; + /* "variant" */ beg = strchr(end + 1, '"'); beg += 1; diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/locale/xkb_layout_ids.c freerdp2-2.3.0+dfsg1/libfreerdp/locale/xkb_layout_ids.c --- freerdp2-2.2.0+dfsg1/libfreerdp/locale/xkb_layout_ids.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/locale/xkb_layout_ids.c 2021-02-25 08:51:41.000000000 +0000 @@ -776,6 +776,7 @@ { "gh", 0, gh_variants }, /* Ghana */ { "gn", 0, NULL }, /* Guinea */ { "ge", KBD_GEORGIAN, ge_variants }, /* Georgia */ + { "at", KBD_GERMAN, de_variants }, /* Austria */ { "de", KBD_GERMAN, de_variants }, /* Germany */ { "gr", KBD_GREEK, gr_variants }, /* Greece */ { "hu", KBD_HUNGARIAN, hu_variants }, /* Hungary */ diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/prim_colors.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/prim_colors.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/prim_colors.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/prim_colors.c 2021-02-25 08:51:41.000000000 +0000 @@ -60,7 +60,7 @@ R = ((INT16)((CrR + Y) >> divisor) >> 5); G = ((INT16)((Y - CbG - CrG) >> divisor) >> 5); B = ((INT16)((CbB + Y) >> divisor) >> 5); - pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0xFF); + pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0); } pY += srcPad; @@ -83,7 +83,7 @@ const INT16* pCr = pSrc[2]; const size_t srcPad = (srcStep - (roi->width * 2)) / 2; const size_t dstPad = (dstStep - (roi->width * 4)); - const fkt_writePixel writePixel = getPixelWriteFunction(DstFormat); + const fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE); const DWORD formatSize = GetBytesPerPixel(DstFormat); for (y = 0; y < roi->height; y++) @@ -102,7 +102,7 @@ R = (INT64)((CrR + Y) >> (divisor + 5)); G = (INT64)((Y - CbG - CrG) >> (divisor + 5)); B = (INT64)((CbB + Y) >> (divisor + 5)); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0); } pY += srcPad; @@ -283,10 +283,10 @@ const INT16* r, const INT16* g, const INT16* b, DWORD width) { DWORD x; - fkt_writePixel writePixel = getPixelWriteFunction(DstFormat); + fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE); for (x = 0; x < width; x++) - dst = (*writePixel)(dst, formatSize, DstFormat, *r++, *g++, *b++, 0xFF); + dst = writePixel(dst, formatSize, DstFormat, *r++, *g++, *b++, 0); } static INLINE void writeScanlineRGB(BYTE* dst, DWORD formatSize, UINT32 DstFormat, const INT16* r, diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/prim_internal.h freerdp2-2.3.0+dfsg1/libfreerdp/primitives/prim_internal.h --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/prim_internal.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/prim_internal.h 2021-02-25 08:51:41.000000000 +0000 @@ -47,14 +47,43 @@ : _mm_load_si128((__m128i*)(_ptr_))) #endif +static INLINE BYTE* writePixelBGRA(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, + BYTE B, BYTE A) +{ + WINPR_UNUSED(formatSize); + WINPR_UNUSED(format); + + *dst++ = B; + *dst++ = G; + *dst++ = R; + *dst++ = A; + return dst; +} + static INLINE BYTE* writePixelBGRX(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, BYTE B, BYTE A) { WINPR_UNUSED(formatSize); WINPR_UNUSED(format); + WINPR_UNUSED(A); + *dst++ = B; *dst++ = G; *dst++ = R; + dst++; /* Do not touch alpha */ + + return dst; +} + +static INLINE BYTE* writePixelRGBA(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, + BYTE B, BYTE A) +{ + WINPR_UNUSED(formatSize); + WINPR_UNUSED(format); + + *dst++ = R; + *dst++ = G; + *dst++ = B; *dst++ = A; return dst; } @@ -64,10 +93,26 @@ { WINPR_UNUSED(formatSize); WINPR_UNUSED(format); + WINPR_UNUSED(A); + *dst++ = R; *dst++ = G; *dst++ = B; + dst++; /* Do not touch alpha */ + + return dst; +} + +static INLINE BYTE* writePixelABGR(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, + BYTE B, BYTE A) +{ + WINPR_UNUSED(formatSize); + WINPR_UNUSED(format); + *dst++ = A; + *dst++ = B; + *dst++ = G; + *dst++ = R; return dst; } @@ -76,18 +121,21 @@ { WINPR_UNUSED(formatSize); WINPR_UNUSED(format); - *dst++ = A; + WINPR_UNUSED(A); + + dst++; /* Do not touch alpha */ *dst++ = B; *dst++ = G; *dst++ = R; return dst; } -static INLINE BYTE* writePixelXRGB(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, +static INLINE BYTE* writePixelARGB(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, BYTE B, BYTE A) { WINPR_UNUSED(formatSize); WINPR_UNUSED(format); + *dst++ = A; *dst++ = R; *dst++ = G; @@ -95,38 +143,60 @@ return dst; } +static INLINE BYTE* writePixelXRGB(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, + BYTE B, BYTE A) +{ + WINPR_UNUSED(formatSize); + WINPR_UNUSED(format); + WINPR_UNUSED(A); + + dst++; /* Do not touch alpha */ + *dst++ = R; + *dst++ = G; + *dst++ = B; + return dst; +} + +static INLINE BYTE* writePixelGenericAlpha(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, + BYTE G, BYTE B, BYTE A) +{ + UINT32 color = FreeRDPGetColor(format, R, G, B, A); + WriteColor(dst, format, color); + return dst + formatSize; +} + static INLINE BYTE* writePixelGeneric(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G, BYTE B, BYTE A) { UINT32 color = FreeRDPGetColor(format, R, G, B, A); - WriteColor(dst, format, color); + WriteColorIgnoreAlpha(dst, format, color); return dst + formatSize; } typedef BYTE* (*fkt_writePixel)(BYTE*, DWORD, UINT32, BYTE, BYTE, BYTE, BYTE); -static INLINE fkt_writePixel getPixelWriteFunction(DWORD format) +static INLINE fkt_writePixel getPixelWriteFunction(DWORD format, BOOL useAlpha) { switch (format) { case PIXEL_FORMAT_ARGB32: case PIXEL_FORMAT_XRGB32: - return writePixelXRGB; + return useAlpha ? writePixelARGB : writePixelXRGB; case PIXEL_FORMAT_ABGR32: case PIXEL_FORMAT_XBGR32: - return writePixelXBGR; + return useAlpha ? writePixelABGR : writePixelXBGR; case PIXEL_FORMAT_RGBA32: case PIXEL_FORMAT_RGBX32: - return writePixelRGBX; + return useAlpha ? writePixelRGBA : writePixelRGBX; case PIXEL_FORMAT_BGRA32: case PIXEL_FORMAT_BGRX32: - return writePixelBGRX; + return useAlpha ? writePixelBGRA : writePixelBGRX; default: - return writePixelGeneric; + return useAlpha ? writePixelGenericAlpha : writePixelGeneric; } } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/primitives.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/primitives.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/primitives.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/primitives.c 2021-02-25 08:51:41.000000000 +0000 @@ -147,13 +147,13 @@ ret->outputStride = roi->width * 4; ret->testedFormat = PIXEL_FORMAT_BGRA32; - ret->outputBuffer = malloc(ret->outputStride * roi->height); + ret->outputBuffer = calloc(ret->outputStride, roi->height); if (!ret->outputBuffer) goto fail; for (i = 0; i < 3; i++) { - BYTE* buf = ret->channels[i] = malloc(roi->width * roi->height); + BYTE* buf = ret->channels[i] = calloc(roi->width, roi->height); if (!buf) goto fail; @@ -172,7 +172,7 @@ UINT64 runTime, UINT32* computations) { ULONGLONG dueDate; - const BYTE* channels[3]; + const BYTE* channels[3] = { 0 }; size_t i; pstatus_t status; diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/prim_YCoCg.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/prim_YCoCg.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/prim_YCoCg.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/prim_YCoCg.c 2021-02-25 08:51:41.000000000 +0000 @@ -37,7 +37,7 @@ const BYTE* sptr = pSrc; INT16 Cg, Co, Y, T, R, G, B; const DWORD formatSize = GetBytesPerPixel(DstFormat); - fkt_writePixel writePixel = getPixelWriteFunction(DstFormat); + fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, TRUE); int cll = shift - 1; /* -1 builds in the /2's */ UINT32 srcPad = srcStep - (width * 4); UINT32 dstPad = dstStep - (width * formatSize); @@ -59,7 +59,7 @@ B = T + Co; G = Y + Cg; R = T - Co; - dptr = (*writePixel)(dptr, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), A); + dptr = writePixel(dptr, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), A); } sptr += srcPad; diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/prim_YUV.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/prim_YUV.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/prim_YUV.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/prim_YUV.c 2021-02-25 08:51:41.000000000 +0000 @@ -385,7 +385,7 @@ UINT32 x, y; UINT32 nWidth, nHeight; const DWORD formatSize = GetBytesPerPixel(DstFormat); - fkt_writePixel writePixel = getPixelWriteFunction(DstFormat); + fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE); nWidth = roi->width; nHeight = roi->height; @@ -404,7 +404,7 @@ const BYTE r = YUV2R(Y, U, V); const BYTE g = YUV2G(Y, U, V); const BYTE b = YUV2B(Y, U, V); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0); } } @@ -437,7 +437,7 @@ const BYTE r = YUV2R(Y, U, V); const BYTE g = YUV2G(Y, U, V); const BYTE b = YUV2B(Y, U, V); - pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixelBGRX(pRGB, formatSize, DstFormat, r, g, b, 0); } } @@ -481,7 +481,7 @@ UINT32 nWidth, nHeight; UINT32 lastRow, lastCol; const DWORD formatSize = GetBytesPerPixel(DstFormat); - fkt_writePixel writePixel = getPixelWriteFunction(DstFormat); + fkt_writePixel writePixel = getPixelWriteFunction(DstFormat, FALSE); pY = pSrc[0]; pU = pSrc[1]; pV = pSrc[2]; @@ -517,7 +517,7 @@ r = YUV2R(Y, U, V); g = YUV2G(Y, U, V); b = YUV2B(Y, U, V); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0); /* 2nd pixel */ if (!(lastCol & 0x02)) @@ -526,7 +526,7 @@ r = YUV2R(Y, U, V); g = YUV2G(Y, U, V); b = YUV2B(Y, U, V); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0); } else { @@ -560,7 +560,7 @@ r = YUV2R(Y, U, V); g = YUV2G(Y, U, V); b = YUV2B(Y, U, V); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0); /* 4th pixel */ if (!(lastCol & 0x02)) @@ -569,7 +569,7 @@ r = YUV2R(Y, U, V); g = YUV2G(Y, U, V); b = YUV2B(Y, U, V); - pRGB = (*writePixel)(pRGB, formatSize, DstFormat, r, g, b, 0xFF); + pRGB = writePixel(pRGB, formatSize, DstFormat, r, g, b, 0); } else { diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/prim_YUV_ssse3.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/prim_YUV_ssse3.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/prim_YUV_ssse3.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/prim_YUV_ssse3.c 2021-02-25 08:51:41.000000000 +0000 @@ -87,7 +87,8 @@ 0x80, 0x03, 0x80, 0x80, 0x80 } }; #endif const __m128i c128 = _mm_set1_epi16(128); - __m128i BGRX = _mm_set_epi32(0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000); + __m128i BGRX = _mm_and_si128(_mm_loadu_si128(dst), + _mm_set_epi32(0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000)); { __m128i C, D, E; /* Load Y values and expand to 32 bit */ @@ -190,7 +191,7 @@ const BYTE r = YUV2R(Y, U, V); const BYTE g = YUV2G(Y, U, V); const BYTE b = YUV2B(Y, U, V); - dst = (__m128i*)writePixelBGRX((BYTE*)dst, 4, PIXEL_FORMAT_BGRX32, r, g, b, 0xFF); + dst = (__m128i*)writePixelBGRX((BYTE*)dst, 4, PIXEL_FORMAT_BGRX32, r, g, b, 0); if (x % 2) { @@ -256,7 +257,7 @@ const BYTE r = YUV2R(Y, U, V); const BYTE g = YUV2G(Y, U, V); const BYTE b = YUV2B(Y, U, V); - dst = (__m128i*)writePixelBGRX((BYTE*)dst, 4, PIXEL_FORMAT_BGRX32, r, g, b, 0xFF); + dst = (__m128i*)writePixelBGRX((BYTE*)dst, 4, PIXEL_FORMAT_BGRX32, r, g, b, 0); } } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesAlphaComp.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesAlphaComp.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesAlphaComp.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesAlphaComp.c 2021-02-25 08:51:41.000000000 +0000 @@ -119,9 +119,9 @@ static BOOL test_alphaComp_func(void) { pstatus_t status; - BYTE ALIGN(src1[SRC1_WIDTH * SRC1_HEIGHT * 4]); - BYTE ALIGN(src2[SRC2_WIDTH * SRC2_HEIGHT * 4]); - BYTE ALIGN(dst1[DST_WIDTH * DST_HEIGHT * 4]); + BYTE ALIGN(src1[SRC1_WIDTH * SRC1_HEIGHT * 4]) = { 0 }; + BYTE ALIGN(src2[SRC2_WIDTH * SRC2_HEIGHT * 4]) = { 0 }; + BYTE ALIGN(dst1[DST_WIDTH * DST_HEIGHT * 4]) = { 0 }; UINT32* ptr; UINT32 i; winpr_RAND((BYTE*)src1, sizeof(src1)); @@ -162,9 +162,9 @@ static int test_alphaComp_speed(void) { - BYTE ALIGN(src1[SRC1_WIDTH * SRC1_HEIGHT]); - BYTE ALIGN(src2[SRC2_WIDTH * SRC2_HEIGHT]); - BYTE ALIGN(dst1[DST_WIDTH * DST_HEIGHT]); + BYTE ALIGN(src1[SRC1_WIDTH * SRC1_HEIGHT]) = { 0 }; + BYTE ALIGN(src2[SRC2_WIDTH * SRC2_HEIGHT]) = { 0 }; + BYTE ALIGN(dst1[DST_WIDTH * DST_HEIGHT]) = { 0 }; char testStr[256]; UINT32* ptr; UINT32 i; @@ -192,6 +192,9 @@ int TestPrimitivesAlphaComp(int argc, char* argv[]) { + WINPR_UNUSED(argc); + WINPR_UNUSED(argv); + prim_test_setup(FALSE); if (!test_alphaComp_func()) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesAndOr.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesAndOr.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesAndOr.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesAndOr.c 2021-02-25 08:51:41.000000000 +0000 @@ -50,7 +50,8 @@ static BOOL test_and_32u_func(void) { - UINT32 ALIGN(src[FUNC_TEST_SIZE + 3]), ALIGN(dst[FUNC_TEST_SIZE + 3]); + UINT32 ALIGN(src[FUNC_TEST_SIZE + 3]) = { 0 }; + UINT32 ALIGN(dst[FUNC_TEST_SIZE + 3]) = { 0 }; winpr_RAND((BYTE*)src, sizeof(src)); @@ -73,7 +74,8 @@ /* ------------------------------------------------------------------------- */ static BOOL test_and_32u_speed(void) { - UINT32 ALIGN(src[MAX_TEST_SIZE + 3]), ALIGN(dst[MAX_TEST_SIZE + 3]); + UINT32 ALIGN(src[MAX_TEST_SIZE + 3]) = { 0 }; + UINT32 ALIGN(dst[MAX_TEST_SIZE + 3]) = { 0 }; winpr_RAND((BYTE*)src, sizeof(src)); @@ -109,7 +111,8 @@ static BOOL test_or_32u_func(void) { pstatus_t status; - UINT32 ALIGN(src[FUNC_TEST_SIZE + 3]), ALIGN(dst[FUNC_TEST_SIZE + 3]); + UINT32 ALIGN(src[FUNC_TEST_SIZE + 3]) = { 0 }; + UINT32 ALIGN(dst[FUNC_TEST_SIZE + 3]) = { 0 }; winpr_RAND((BYTE*)src, sizeof(src)); @@ -133,7 +136,8 @@ /* ------------------------------------------------------------------------- */ static BOOL test_or_32u_speed(void) { - UINT32 ALIGN(src[FUNC_TEST_SIZE + 3]), ALIGN(dst[FUNC_TEST_SIZE + 3]); + UINT32 ALIGN(src[FUNC_TEST_SIZE + 3]) = { 0 }; + UINT32 ALIGN(dst[FUNC_TEST_SIZE + 3]) = { 0 }; char testStr[256]; testStr[0] = '\0'; winpr_RAND((BYTE*)src, sizeof(src)); @@ -147,6 +151,9 @@ int TestPrimitivesAndOr(int argc, char* argv[]) { + WINPR_UNUSED(argc); + WINPR_UNUSED(argv); + prim_test_setup(FALSE); if (!test_and_32u_func()) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesColors.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesColors.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesColors.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesColors.c 2021-02-25 08:51:41.000000000 +0000 @@ -38,11 +38,11 @@ PROFILER_DEFINE(optProf) PROFILER_CREATE(genericProf, "RGBToRGB_16s8u_P3AC4R-GENERIC") PROFILER_CREATE(optProf, "RGBToRGB_16s8u_P3AC4R-OPTIMIZED") - r = _aligned_malloc(rgbStride * roi.height, 16); - g = _aligned_malloc(rgbStride * roi.height, 16); - b = _aligned_malloc(rgbStride * roi.height, 16); - out1 = _aligned_malloc(dstStride * roi.height, 16); - out2 = _aligned_malloc(dstStride * roi.height, 16); + r = _aligned_recalloc(NULL, 1, rgbStride * roi.height, 16); + g = _aligned_recalloc(NULL, 1, rgbStride * roi.height, 16); + b = _aligned_recalloc(NULL, 1, rgbStride * roi.height, 16); + out1 = _aligned_recalloc(NULL, 1, dstStride * roi.height, 16); + out2 = _aligned_recalloc(NULL, 1, dstStride * roi.height, 16); if (!r || !g || !b || !out1 || !out2) goto fail; diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesCopy.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesCopy.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesCopy.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesCopy.c 2021-02-25 08:51:41.000000000 +0000 @@ -25,9 +25,9 @@ static BOOL test_copy8u_func(void) { primitives_t* prims = primitives_get(); - BYTE ALIGN(data[COPY_TESTSIZE + 15]); + BYTE ALIGN(data[COPY_TESTSIZE + 15]) = { 0 }; int i, soff; - BYTE ALIGN(dest[COPY_TESTSIZE + 15]); + BYTE ALIGN(dest[COPY_TESTSIZE + 15]) = { 0 }; winpr_RAND(data, sizeof(data)); for (soff = 0; soff < 16; ++soff) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesSign.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesSign.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesSign.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesSign.c 2021-02-25 08:51:41.000000000 +0000 @@ -25,9 +25,9 @@ static BOOL test_sign16s_func(void) { pstatus_t status; - INT16 ALIGN(src[TEST_BUFFER_SIZE + 16]); - INT16 ALIGN(d1[TEST_BUFFER_SIZE + 16]); - INT16 ALIGN(d2[TEST_BUFFER_SIZE + 16]); + INT16 ALIGN(src[TEST_BUFFER_SIZE + 16]) = { 0 }; + INT16 ALIGN(d1[TEST_BUFFER_SIZE + 16]) = { 0 }; + INT16 ALIGN(d2[TEST_BUFFER_SIZE + 16]) = { 0 }; winpr_RAND((BYTE*)src, sizeof(src)); memset(d1, 0, sizeof(d1)); memset(d2, 0, sizeof(d2)); @@ -62,7 +62,8 @@ static int test_sign16s_speed(void) { - INT16 ALIGN(src[MAX_TEST_SIZE + 3]), ALIGN(dst[MAX_TEST_SIZE + 3]); + INT16 ALIGN(src[MAX_TEST_SIZE + 3]) = { 0 }; + INT16 ALIGN(dst[MAX_TEST_SIZE + 3]) = { 0 }; winpr_RAND((BYTE*)src, sizeof(src)); if (!speed_test("sign16s", "aligned", g_Iterations, (speed_test_fkt)generic->sign_16s, @@ -78,6 +79,9 @@ int TestPrimitivesSign(int argc, char* argv[]) { + WINPR_UNUSED(argc); + WINPR_UNUSED(argv); + prim_test_setup(FALSE); if (!test_sign16s_func()) diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesYCoCg.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesYCoCg.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesYCoCg.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesYCoCg.c 2021-02-25 08:51:41.000000000 +0000 @@ -38,9 +38,9 @@ PIXEL_FORMAT_RGBX32, PIXEL_FORMAT_BGRA32, PIXEL_FORMAT_BGRX32 }; PROFILER_DEFINE(genericProf) PROFILER_DEFINE(optProf) - in = _aligned_malloc(size, 16); - out_c = _aligned_malloc(size, 16); - out_sse = _aligned_malloc(size, 16); + in = _aligned_recalloc(NULL, 1, size, 16); + out_c = _aligned_recalloc(NULL, 1, size, 16); + out_sse = _aligned_recalloc(NULL, 1, size, 16); if (!in || !out_c || !out_sse) goto fail; @@ -111,6 +111,8 @@ int TestPrimitivesYCoCg(int argc, char* argv[]) { + WINPR_UNUSED(argc); + WINPR_UNUSED(argv); prim_test_setup(FALSE); /* Random resolution tests */ diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesYUV.c freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesYUV.c --- freerdp2-2.2.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesYUV.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/primitives/test/TestPrimitivesYUV.c 2021-02-25 08:51:41.000000000 +0000 @@ -14,6 +14,8 @@ #define TAG __FILE__ +#define PADDING_FILL_VALUE 0x37 + /* YUV to RGB conversion is lossy, so consider every value only * differing by less than 2 abs equal. */ static BOOL similar(const BYTE* src, const BYTE* dst, size_t size) @@ -35,10 +37,13 @@ return TRUE; } -static BOOL similarRGB(const BYTE* src, const BYTE* dst, size_t size, UINT32 format) +static BOOL similarRGB(const BYTE* src, const BYTE* dst, size_t size, UINT32 format, BOOL use444) { size_t x; const UINT32 bpp = GetBytesPerPixel(format); + BYTE fill = PADDING_FILL_VALUE; + if (!ColorHasAlpha(format)) + fill = 0xFF; for (x = 0; x < size; x++) { @@ -57,14 +62,15 @@ { fprintf( stderr, - "Color value mismatch R[%02X %02X], G[%02X %02X], B[%02X %02X] at position %lu", + "Color value mismatch R[%02X %02X], G[%02X %02X], B[%02X %02X] at position %lu\n", sR, dR, sG, dG, sA, dA, x); return FALSE; } - if (dA != 0xFF) + if (dA != fill) { - fprintf(stderr, "Invalid destination alpha value %02X at position %lu", dA, x); + fprintf(stderr, "[%s] Invalid destination alpha value %02X at position %lu\n", + use444 ? "AVC444" : "AVC420", dA, x); return FALSE; } } @@ -141,7 +147,7 @@ return NULL; memset(&src[0], 'A', halfPad); - memset(&src[halfPad], 0, size); + memset(&src[halfPad], PADDING_FILL_VALUE, size); memset(&src[halfPad + size], 'A', halfPad); psrc = &src[halfPad]; @@ -448,6 +454,8 @@ pstatus_t rc; const UINT32 DstFormat = formats[x]; printf("Testing destination color format %s\n", FreeRDPGetColorFormatName(DstFormat)); + memset(rgb_dst, PADDING_FILL_VALUE, size * sizeof(UINT32)); + PROFILER_CREATE(rgbToYUV420, "RGBToYUV420") PROFILER_CREATE(rgbToYUV444, "RGBToYUV444") PROFILER_CREATE(yuv420ToRGB, "YUV420ToRGB") @@ -543,7 +551,7 @@ BYTE* srgb = &rgb[y * stride]; BYTE* drgb = &rgb_dst[y * stride]; - if (!similarRGB(srgb, drgb, roi.width, DstFormat)) + if (!similarRGB(srgb, drgb, roi.width, DstFormat, use444)) goto fail; } diff -Nru freerdp2-2.2.0+dfsg1/libfreerdp/utils/pcap.c freerdp2-2.3.0+dfsg1/libfreerdp/utils/pcap.c --- freerdp2-2.2.0+dfsg1/libfreerdp/utils/pcap.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/libfreerdp/utils/pcap.c 2021-02-25 08:51:41.000000000 +0000 @@ -95,10 +95,10 @@ static BOOL pcap_write_record(rdpPcap* pcap, pcap_record* record) { return pcap_write_record_header(pcap, &record->header) && - (fwrite(record->data, record->length, 1, pcap->fp) == 1); + (fwrite(record->cdata, record->length, 1, pcap->fp) == 1); } -BOOL pcap_add_record(rdpPcap* pcap, void* data, UINT32 length) +BOOL pcap_add_record(rdpPcap* pcap, const void* data, UINT32 length) { pcap_record* record; struct timeval tp; @@ -126,7 +126,7 @@ if (pcap->record == NULL) pcap->record = record; - record->data = data; + record->cdata = data; record->length = length; record->header.incl_len = length; record->header.orig_len = length; diff -Nru freerdp2-2.2.0+dfsg1/scripts/android-build-32.conf freerdp2-2.3.0+dfsg1/scripts/android-build-32.conf --- freerdp2-2.2.0+dfsg1/scripts/android-build-32.conf 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/scripts/android-build-32.conf 2021-02-25 08:51:41.000000000 +0000 @@ -10,15 +10,15 @@ # create seperate configurations for each NDK API level # and architecture you want to support. WITH_JPEG=0 -WITH_OPENH264=0 +WITH_OPENH264=1 WITH_OPENSSL=1 BUILD_DEPS=1 DEPS_ONLY=0 -NDK_TARGET=14 +NDK_TARGET=21 JPEG_TAG=master -OPENH264_TAG=v1.8.0 -OPENSSL_TAG=OpenSSL_1_1_1f +OPENH264_TAG=v1.8.0 # NOTE: NDK r15c or earlier needed in --openh624-ndk for v1.8.0 +OPENSSL_TAG=OpenSSL_1_1_1h SRC_DIR=$SCRIPT_PATH/.. BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs diff -Nru freerdp2-2.2.0+dfsg1/scripts/android-build-64.conf freerdp2-2.3.0+dfsg1/scripts/android-build-64.conf --- freerdp2-2.2.0+dfsg1/scripts/android-build-64.conf 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/scripts/android-build-64.conf 2021-02-25 08:51:41.000000000 +0000 @@ -10,15 +10,15 @@ # create seperate configurations for each NDK API level # and architecture you want to support. WITH_JPEG=0 -WITH_OPENH264=0 +WITH_OPENH264=1 WITH_OPENSSL=1 BUILD_DEPS=1 DEPS_ONLY=0 NDK_TARGET=21 JPEG_TAG=master -OPENH264_TAG=v1.8.0 -OPENSSL_TAG=OpenSSL_1_1_1f +OPENH264_TAG=v1.8.0 # NOTE: NDK r15c or earlier needed in --openh624-ndk for v1.8.0 +OPENSSL_TAG=OpenSSL_1_1_1h SRC_DIR=$SCRIPT_PATH/.. BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs diff -Nru freerdp2-2.2.0+dfsg1/scripts/android-build.conf freerdp2-2.3.0+dfsg1/scripts/android-build.conf --- freerdp2-2.2.0+dfsg1/scripts/android-build.conf 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/scripts/android-build.conf 2021-02-25 08:51:41.000000000 +0000 @@ -17,8 +17,8 @@ NDK_TARGET=26 JPEG_TAG=master -OPENH264_TAG=v1.8.0 -OPENSSL_TAG=OpenSSL_1_1_1f +OPENH264_TAG=v1.8.0 # NOTE: NDK r15c or earlier needed in --openh624-ndk for v1.8.0 +OPENSSL_TAG=OpenSSL_1_1_1h SRC_DIR=$SCRIPT_PATH/.. BUILD_DST=$SCRIPT_PATH/../client/Android/Studio/freeRDPCore/src/main/jniLibs diff -Nru freerdp2-2.2.0+dfsg1/scripts/android-build-freerdp.sh freerdp2-2.3.0+dfsg1/scripts/android-build-freerdp.sh --- freerdp2-2.2.0+dfsg1/scripts/android-build-freerdp.sh 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/scripts/android-build-freerdp.sh 2021-02-25 08:51:41.000000000 +0000 @@ -8,7 +8,8 @@ WITH_OPENH264=0 WITH_OPENSSL=0 -SRC_DIR=$(pwd) +SRC_DIR=$(dirname "${BASH_SOURCE[0]}") +SRC_DIR=$(realpath "$SRC_DIR") BUILD_SRC=$(pwd) BUILD_DST=$(pwd) @@ -37,6 +38,11 @@ WITH_OPENH264=1 shift ;; + --openh264-ndk) + shift + ANDROID_NDK_OPENH264=$1 + shift + ;; --openssl) WITH_OPENSSL=1 shift @@ -107,11 +113,19 @@ fi if [ $WITH_OPENH264 -ne 0 ]; then + if [ -z "$ANDROID_NDK_OPENH264" ] + then + echo + echo "Warning: Missing openh264-ndk, using $ANDROID_NDK" >&2 + echo + ANDROID_NDK_OPENH264=$ANDROID_NDK + fi if [ $BUILD_DEPS -ne 0 ]; then common_run bash $SCRIPT_PATH/android-build-openh264.sh \ --src $BUILD_SRC/openh264 --dst $BUILD_DST \ - --ndk $ANDROID_NDK \ + --sdk "$ANDROID_SDK" \ + --ndk "$ANDROID_NDK_OPENH264" \ --arch $ARCH \ --target $NDK_TARGET \ --tag $OPENH264_TAG @@ -126,6 +140,7 @@ then common_run bash $SCRIPT_PATH/android-build-openssl.sh \ --src $BUILD_SRC/openssl --dst $BUILD_DST \ + --sdk "$ANDROID_SDK" \ --ndk $ANDROID_NDK \ --arch $ARCH \ --target $NDK_TARGET \ diff -Nru freerdp2-2.2.0+dfsg1/scripts/android-build-openssl.sh freerdp2-2.3.0+dfsg1/scripts/android-build-openssl.sh --- freerdp2-2.2.0+dfsg1/scripts/android-build-openssl.sh 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/scripts/android-build-openssl.sh 2021-02-25 08:51:41.000000000 +0000 @@ -19,6 +19,7 @@ common_run export CC=clang common_run export PATH=$(${SCRIPT_PATH}/toolchains_path.py --ndk ${ANDROID_NDK}):$ORG_PATH + common_run export ANDROID_NDK echo "CONFIG=$CONFIG" echo "DST_PREFIX=$DST_PREFIX" diff -Nru freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_main.c freerdp2-2.3.0+dfsg1/server/proxy/modules/capture/cap_main.c --- freerdp2-2.2.0+dfsg1/server/proxy/modules/capture/cap_main.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/server/proxy/modules/capture/cap_main.c 2021-02-25 08:51:41.000000000 +0000 @@ -127,7 +127,7 @@ wStream* s; socket = capture_plugin_get_socket(pdata); - if (socket == -1) + if (socket == INVALID_SOCKET) return FALSE; s = capture_plugin_packet_new(SESSION_END_PDU_BASE_SIZE, MESSAGE_TYPE_SESSION_END); @@ -191,7 +191,7 @@ return TRUE; socket = capture_plugin_get_socket(pdata); - if (socket == -1) + if (socket == INVALID_SOCKET) return FALSE; if (!capture_plugin_send_frame(pc, socket, gdi->primary_buffer)) @@ -213,7 +213,7 @@ rdpSettings* settings = pc->context.settings; socket = capture_plugin_init_socket(); - if (socket == -1) + if (socket == INVALID_SOCKET) { WLog_ERR(TAG, "failed to establish a connection"); return FALSE; diff -Nru freerdp2-2.2.0+dfsg1/server/proxy/pf_cliprdr.c freerdp2-2.3.0+dfsg1/server/proxy/pf_cliprdr.c --- freerdp2-2.2.0+dfsg1/server/proxy/pf_cliprdr.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/server/proxy/pf_cliprdr.c 2021-02-25 08:51:41.000000000 +0000 @@ -45,6 +45,7 @@ cliprdr->streamFileClipEnabled = TRUE; cliprdr->fileClipNoFilePaths = TRUE; cliprdr->canLockClipData = TRUE; + cliprdr->hasHugeFileSupport = TRUE; /* disable initialization sequence, for caps sync */ cliprdr->autoInitializationSequence = FALSE; diff -Nru freerdp2-2.2.0+dfsg1/server/proxy/pf_context.c freerdp2-2.3.0+dfsg1/server/proxy/pf_context.c --- freerdp2-2.2.0+dfsg1/server/proxy/pf_context.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/server/proxy/pf_context.c 2021-02-25 08:51:41.000000000 +0000 @@ -39,8 +39,9 @@ } /* Proxy context initialization callback */ -static BOOL client_to_proxy_context_new(freerdp_peer* client, pServerContext* context) +static BOOL client_to_proxy_context_new(freerdp_peer* client, rdpContext* ctx) { + pServerContext* context = (pServerContext*)ctx; proxyServer* server = (proxyServer*)client->ContextExtra; proxyConfig* config = server->config; @@ -82,8 +83,9 @@ } /* Proxy context free callback */ -static void client_to_proxy_context_free(freerdp_peer* client, pServerContext* context) +static void client_to_proxy_context_free(freerdp_peer* client, rdpContext* ctx) { + pServerContext* context = (pServerContext*)ctx; proxyServer* server; if (!client || !context) @@ -106,8 +108,8 @@ BOOL pf_context_init_server_context(freerdp_peer* client) { client->ContextSize = sizeof(pServerContext); - client->ContextNew = (psPeerContextNew)client_to_proxy_context_new; - client->ContextFree = (psPeerContextFree)client_to_proxy_context_free; + client->ContextNew = client_to_proxy_context_new; + client->ContextFree = client_to_proxy_context_free; return freerdp_peer_context_new(client); } diff -Nru freerdp2-2.2.0+dfsg1/server/shadow/shadow_client.c freerdp2-2.3.0+dfsg1/server/shadow/shadow_client.c --- freerdp2-2.2.0+dfsg1/server/shadow/shadow_client.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/server/shadow/shadow_client.c 2021-02-25 08:51:41.000000000 +0000 @@ -927,11 +927,11 @@ int nXSrc, int nYSrc, int nWidth, int nHeight) { BOOL ret = TRUE; - int i; + size_t i; BOOL first; BOOL last; wStream* s; - int numMessages; + size_t numMessages; UINT32 frameId = 0; rdpUpdate* update; rdpContext* context = (rdpContext*)client; @@ -970,11 +970,11 @@ rect.width = nWidth; rect.height = nHeight; - if (!(messages = rfx_encode_messages( + if (!(messages = rfx_encode_messages_ex( encoder->rfx, &rect, 1, pSrcData, settings->DesktopWidth, settings->DesktopHeight, nSrcStep, &numMessages, settings->MultifragMaxRequestSize))) { - WLog_ERR(TAG, "rfx_encode_messages failed"); + WLog_ERR(TAG, "rfx_encode_messages_ex failed"); return FALSE; } diff -Nru freerdp2-2.2.0+dfsg1/.travis.yml freerdp2-2.3.0+dfsg1/.travis.yml --- freerdp2-2.2.0+dfsg1/.travis.yml 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/.travis.yml 2021-02-25 08:51:41.000000000 +0000 @@ -43,12 +43,15 @@ - 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 diff -Nru freerdp2-2.2.0+dfsg1/uwac/include/uwac/uwac.h freerdp2-2.3.0+dfsg1/uwac/include/uwac/uwac.h --- freerdp2-2.2.0+dfsg1/uwac/include/uwac/uwac.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/uwac/include/uwac/uwac.h 2021-02-25 08:51:41.000000000 +0000 @@ -62,6 +62,8 @@ UWAC_MOD_SHIFT_MASK = 0x01, UWAC_MOD_ALT_MASK = 0x02, UWAC_MOD_CONTROL_MASK = 0x04, + UWAC_MOD_CAPS_MASK = 0x08, + UWAC_MOD_NUM_MASK = 0x10, }; /** @brief a position */ @@ -104,6 +106,8 @@ UWAC_EVENT_CLIPBOARD_SELECT, UWAC_EVENT_CLIPBOARD_OFFER, UWAC_EVENT_OUTPUT_GEOMETRY, + UWAC_EVENT_KEYBOARD_MODIFIERS, + UWAC_EVENT_POINTER_AXIS_DISCRETE }; /** @brief window states */ @@ -144,6 +148,13 @@ }; typedef struct uwac_keyboard_enter_event UwacKeyboardEnterLeaveEvent; +struct uwac_keyboard_modifiers_event +{ + int type; + uint32_t modifiers; +}; +typedef struct uwac_keyboard_modifiers_event UwacKeyboardModifiersEvent; + struct uwac_pointer_enter_event { int type; @@ -276,6 +287,7 @@ UwacPointerButtonEvent mouse_button; UwacPointerAxisEvent mouse_axis; UwacKeyboardEnterLeaveEvent keyboard_enter_leave; + UwacKeyboardModifiersEvent keyboard_modifiers; UwacClipboardEvent clipboard; UwacKeyEvent key; UwacTouchFrameBegin touchFrameBegin; diff -Nru freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-input.c freerdp2-2.3.0+dfsg1/uwac/libuwac/uwac-input.c --- freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-input.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/uwac/libuwac/uwac-input.c 2021-02-25 08:51:41.000000000 +0000 @@ -168,6 +168,7 @@ key->window = window; key->sym = input->repeat_sym; + key->raw_key = input->repeat_key; key->pressed = true; } } @@ -230,6 +231,8 @@ input->xkb.control_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Control"); input->xkb.alt_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Mod1"); input->xkb.shift_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Shift"); + input->xkb.caps_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Lock"); + input->xkb.num_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Mod2"); } static void keyboard_handle_key(void* data, struct wl_keyboard* keyboard, uint32_t serial, @@ -424,6 +427,7 @@ uint32_t mods_locked, uint32_t group) { UwacSeat* input = data; + UwacKeyboardModifiersEvent* event; xkb_mod_mask_t mask; /* If we're not using a keymap, then we don't handle PC-style modifiers */ @@ -431,8 +435,9 @@ return; xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched, mods_locked, 0, 0, group); - mask = xkb_state_serialize_mods(input->xkb.state, - XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); + mask = xkb_state_serialize_mods(input->xkb.state, XKB_STATE_MODS_DEPRESSED | + XKB_STATE_MODS_LATCHED | + XKB_STATE_MODS_LOCKED); input->modifiers = 0; if (mask & input->xkb.control_mask) input->modifiers |= UWAC_MOD_CONTROL_MASK; @@ -440,6 +445,17 @@ input->modifiers |= UWAC_MOD_ALT_MASK; if (mask & input->xkb.shift_mask) input->modifiers |= UWAC_MOD_SHIFT_MASK; + if (mask & input->xkb.caps_mask) + input->modifiers |= UWAC_MOD_CAPS_MASK; + if (mask & input->xkb.num_mask) + input->modifiers |= UWAC_MOD_NUM_MASK; + + event = (UwacKeyboardModifiersEvent*)UwacDisplayNewEvent(input->display, + UWAC_EVENT_KEYBOARD_MODIFIERS); + if (!event) + return; + + event->modifiers = input->modifiers; } static void set_repeat_info(UwacSeat* input, int32_t rate, int32_t delay) @@ -846,6 +862,24 @@ int32_t discrete) { /*UwacSeat *seat = data;*/ + UwacPointerAxisEvent* event; + UwacSeat* seat = data; + UwacWindow* window = seat->pointer_focus; + + if (!window) + return; + + event = + (UwacPointerAxisEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_AXIS_DISCRETE); + if (!event) + return; + + event->seat = seat; + event->window = window; + event->x = seat->sx; + event->y = seat->sy; + event->axis = axis; + event->value = discrete; } static const struct wl_pointer_listener pointer_listener = { diff -Nru freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-priv.h freerdp2-2.3.0+dfsg1/uwac/libuwac/uwac-priv.h --- freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-priv.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/uwac/libuwac/uwac-priv.h 2021-02-25 08:51:41.000000000 +0000 @@ -180,6 +180,8 @@ xkb_mod_mask_t control_mask; xkb_mod_mask_t alt_mask; xkb_mod_mask_t shift_mask; + xkb_mod_mask_t caps_mask; + xkb_mod_mask_t num_mask; } xkb; uint32_t modifiers; int32_t repeat_rate_sec, repeat_rate_nsec; diff -Nru freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-window.c freerdp2-2.3.0+dfsg1/uwac/libuwac/uwac-window.c --- freerdp2-2.2.0+dfsg1/uwac/libuwac/uwac-window.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/uwac/libuwac/uwac-window.c 2021-02-25 08:51:41.000000000 +0000 @@ -176,8 +176,6 @@ uint32_t serial) { xdg_surface_ack_configure(xdg_surface, serial); - UwacWindow* window = (UwacWindow*)data; - wl_surface_commit(window->surface); } static const struct xdg_surface_listener xdg_surface_listener = { diff -Nru freerdp2-2.2.0+dfsg1/winpr/CMakeLists.txt freerdp2-2.3.0+dfsg1/winpr/CMakeLists.txt --- freerdp2-2.2.0+dfsg1/winpr/CMakeLists.txt 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/CMakeLists.txt 2021-02-25 08:51:41.000000000 +0000 @@ -51,7 +51,7 @@ endif() # Soname versioning -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) diff -Nru freerdp2-2.2.0+dfsg1/winpr/include/winpr/cmdline.h freerdp2-2.3.0+dfsg1/winpr/include/winpr/cmdline.h --- freerdp2-2.2.0+dfsg1/winpr/include/winpr/cmdline.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/include/winpr/cmdline.h 2021-02-25 08:51:41.000000000 +0000 @@ -81,6 +81,7 @@ #define COMMAND_LINE_STATUS_PRINT_HELP -2002 #define COMMAND_LINE_STATUS_PRINT_VERSION -2003 #define COMMAND_LINE_STATUS_PRINT_BUILDCONFIG -2004 +#define COMMAND_LINE_STATUS_PRINT_LAST -2999 /* Command-Line Macros */ diff -Nru freerdp2-2.2.0+dfsg1/winpr/include/winpr/shell.h freerdp2-2.3.0+dfsg1/winpr/include/winpr/shell.h --- freerdp2-2.2.0+dfsg1/winpr/include/winpr/shell.h 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/include/winpr/shell.h 2021-02-25 08:51:41.000000000 +0000 @@ -36,6 +36,23 @@ /* Shell clipboard formats */ +struct _FILEDESCRIPTORW +{ + DWORD dwFlags; + CLSID clsid; + SIZEL sizel; + POINTL pointl; + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; + WCHAR cFileName[260]; +}; +typedef struct _FILEDESCRIPTORW FILEDESCRIPTORW; + +/* Legacy definition, some types do not match the windows equivalent. */ struct _FILEDESCRIPTOR { DWORD dwFlags; @@ -53,10 +70,22 @@ typedef struct _FILEDESCRIPTOR FILEDESCRIPTOR; /* FILEDESCRIPTOR.dwFlags */ -#define FD_ATTRIBUTES 0x00000004 -#define FD_FILESIZE 0x00000040 -#define FD_WRITESTIME 0x00000020 -#define FD_SHOWPROGRESSUI 0x00004000 +typedef enum +{ + FD_CLSID = 0x00000001, + FD_SIZEPOINT = 0x00000002, + FD_ATTRIBUTES = 0x00000004, + FD_CREATETIME = 0x00000008, + FD_ACCESSTIME = 0x00000010, + FD_WRITETIME = 0x00000020, + FD_FILESIZE = 0x00000040, + FD_PROGRESSUI = 0x00004000, + FD_LINKUI = 0x00008000, + FD_UNICODE = 0x80000000 +} FD_FLAGS; + +/* Deprecated, here for compatibility */ +#define FD_SHOWPROGRESSUI FD_PROGRESSUI /* FILEDESCRIPTOR.dwFileAttributes */ #define FILE_ATTRIBUTE_READONLY 0x00000001 diff -Nru freerdp2-2.2.0+dfsg1/winpr/include/winpr/wtypes.h.in freerdp2-2.3.0+dfsg1/winpr/include/winpr/wtypes.h.in --- freerdp2-2.2.0+dfsg1/winpr/include/winpr/wtypes.h.in 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/include/winpr/wtypes.h.in 2021-02-25 08:51:41.000000000 +0000 @@ -268,6 +268,20 @@ typedef LONG SCODE; typedef SCODE* PSCODE; +typedef struct _POINTL /* ptl */ +{ + LONG x; + LONG y; +} POINTL, *PPOINTL; + +typedef struct tagSIZE +{ + LONG cx; + LONG cy; +} SIZE, *PSIZE, *LPSIZE; + +typedef SIZE SIZEL; + typedef struct _GUID { UINT32 Data1; @@ -275,6 +289,7 @@ UINT16 Data3; BYTE Data4[8]; } GUID, UUID, *PGUID, *LPGUID, *LPCGUID; +typedef GUID CLSID; typedef struct _LUID { diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/clipboard/posix.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/clipboard/posix.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/clipboard/posix.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/clipboard/posix.c 2021-02-25 08:51:41.000000000 +0000 @@ -22,6 +22,7 @@ #endif #define _FILE_OFFSET_BITS 64 +#define WIN32_FILETIME_TO_UNIX_EPOCH UINT64_C(11644473600) #include #include @@ -52,6 +53,7 @@ char* local_name; WCHAR* remote_name; BOOL is_directory; + UINT64 last_write_time; int fd; INT64 offset; @@ -83,6 +85,7 @@ } file->is_directory = S_ISDIR(statbuf.st_mode); + file->last_write_time = (statbuf.st_mtime + WIN32_FILETIME_TO_UNIX_EPOCH) * 10 * 1000 * 1000; file->size = statbuf.st_size; return file; error: @@ -496,10 +499,10 @@ } static BOOL convert_local_file_to_filedescriptor(const struct posix_file* file, - FILEDESCRIPTOR* descriptor) + FILEDESCRIPTORW* descriptor) { size_t remote_len = 0; - descriptor->dwFlags = FD_ATTRIBUTES | FD_FILESIZE | FD_SHOWPROGRESSUI; + descriptor->dwFlags = FD_ATTRIBUTES | FD_FILESIZE | FD_WRITETIME | FD_PROGRESSUI; if (file->is_directory) { @@ -513,6 +516,8 @@ descriptor->nFileSizeLow = (file->size >> 0) & 0xFFFFFFFF; descriptor->nFileSizeHigh = (file->size >> 32) & 0xFFFFFFFF; } + descriptor->ftLastWriteTime.dwLowDateTime = (file->last_write_time >> 0) & 0xFFFFFFFF; + descriptor->ftLastWriteTime.dwHighDateTime = (file->last_write_time >> 32) & 0xFFFFFFFF; remote_len = _wcslen(file->remote_name); @@ -526,11 +531,11 @@ return TRUE; } -static FILEDESCRIPTOR* convert_local_file_list_to_filedescriptors(wArrayList* files) +static FILEDESCRIPTORW* convert_local_file_list_to_filedescriptors(wArrayList* files) { int i; int count = 0; - FILEDESCRIPTOR* descriptors = NULL; + FILEDESCRIPTORW* descriptors = NULL; count = ArrayList_Count(files); descriptors = calloc(count, sizeof(descriptors[0])); @@ -554,7 +559,7 @@ static void* convert_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) { - FILEDESCRIPTOR* descriptors = NULL; + FILEDESCRIPTORW* descriptors = NULL; if (!clipboard || !data || !pSize) return NULL; @@ -570,7 +575,7 @@ if (!descriptors) return NULL; - *pSize = ArrayList_Count(clipboard->localFiles) * sizeof(FILEDESCRIPTOR); + *pSize = ArrayList_Count(clipboard->localFiles) * sizeof(FILEDESCRIPTORW); clipboard->fileListSequenceNumber = clipboard->sequenceNumber; return descriptors; } @@ -578,7 +583,7 @@ static void* convert_filedescriptors_to_uri_list(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize) { - const FILEDESCRIPTOR* descriptors; + const FILEDESCRIPTORW* descriptors; UINT32 nrDescriptors = 0; size_t count, x, alloc, pos, baseLength = 0; const char* src = (const char*)data; @@ -600,12 +605,12 @@ nrDescriptors = (UINT32)(src[3] << 24) | (UINT32)(src[2] << 16) | (UINT32)(src[1] << 8) | (src[0] & 0xFF); - count = (*pSize - 4) / sizeof(FILEDESCRIPTOR); + count = (*pSize - 4) / sizeof(FILEDESCRIPTORW); if ((count < 1) || (count != nrDescriptors)) return NULL; - descriptors = (const FILEDESCRIPTOR*)&src[4]; + descriptors = (const FILEDESCRIPTORW*)&src[4]; if (formatId != ClipboardGetFormatId(clipboard, "FileGroupDescriptorW")) return NULL; @@ -628,7 +633,7 @@ for (x = 0; x < count; x++) { int rc; - const FILEDESCRIPTOR* cur = &descriptors[x]; + const FILEDESCRIPTORW* cur = &descriptors[x]; size_t curLen = _wcsnlen(cur->cFileName, ARRAYSIZE(cur->cFileName)); char* curName = NULL; rc = ConvertFromUnicode(CP_UTF8, 0, cur->cFileName, (int)curLen, &curName, 0, NULL, NULL); @@ -659,6 +664,7 @@ static BOOL register_file_formats_and_synthesizers(wClipboard* clipboard) { + wObject* obj; UINT32 file_group_format_id; UINT32 local_file_format_id; file_group_format_id = ClipboardRegisterFormat(clipboard, "FileGroupDescriptorW"); @@ -672,7 +678,10 @@ if (!clipboard->localFiles) goto error; - ArrayList_Object(clipboard->localFiles)->fnObjectFree = free_posix_file; + obj = ArrayList_Object(clipboard->localFiles); + if (!obj) + goto error; + obj->fnObjectFree = free_posix_file; if (!ClipboardRegisterSynthesizer(clipboard, local_file_format_id, file_group_format_id, convert_uri_list_to_filedescriptors)) diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/crt/alignment.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/crt/alignment.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/crt/alignment.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/crt/alignment.c 2021-02-25 08:51:41.000000000 +0000 @@ -177,7 +177,7 @@ ZeroMemory(newMemblock, pNewMem->size); } - return memblock; + return newMemblock; } pMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(memblock); diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/crt/string.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/crt/string.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/crt/string.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/crt/string.c 2021-02-25 08:51:41.000000000 +0000 @@ -52,20 +52,13 @@ WCHAR* _wcsdup(const WCHAR* strSource) { + size_t len = _wcslen(strSource); WCHAR* strDestination; - if (strSource == NULL) - return NULL; - -#if defined(__APPLE__) && defined(__MACH__) || defined(ANDROID) || defined(sun) - strDestination = malloc(wcslen((wchar_t*)strSource)); + strDestination = calloc(len + 1, sizeof(WCHAR)); if (strDestination != NULL) - wcscpy((wchar_t*)strDestination, (const wchar_t*)strSource); - -#else - strDestination = (WCHAR*)wcsdup((wchar_t*)strSource); -#endif + memcpy(strDestination, strSource, len * sizeof(WCHAR)); if (strDestination == NULL) WLog_ERR(TAG, "wcsdup"); diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/crt/test/TestUnicodeConversion.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/crt/test/TestUnicodeConversion.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/crt/test/TestUnicodeConversion.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/crt/test/TestUnicodeConversion.c 2021-02-25 08:51:41.000000000 +0000 @@ -411,6 +411,31 @@ int ii; size_t i; + /* Test static string buffers of differing sizes */ + { + char name[] = "someteststring"; + const WCHAR cmp[] = { L's', L'o', L'm', L'e', L't', L'e', L's', L't', + L's', L't', L'r', L'i', L'n', L'g', 0 }; + WCHAR xname[128] = { 0 }; + LPWSTR aname = NULL; + LPWSTR wname = &xname[0]; + const size_t len = strnlen(name, ARRAYSIZE(name) - 1); + ii = ConvertToUnicode(CP_UTF8, 0, name, len, &wname, ARRAYSIZE(xname)); + if (ii != len) + goto fail; + + if (memcmp(wname, cmp, sizeof(cmp)) != 0) + goto fail; + + ii = ConvertToUnicode(CP_UTF8, 0, name, len, &aname, 0); + if (ii != len) + goto fail; + ii = memcmp(aname, cmp, sizeof(cmp)); + free(aname); + if (ii != 0) + goto fail; + } + /* Test unterminated unicode string: * ConvertToUnicode must always null-terminate, even if the src string isn't */ diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/crt/unicode.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/crt/unicode.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/crt/unicode.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/crt/unicode.c 2021-02-25 08:51:41.000000000 +0000 @@ -429,9 +429,8 @@ { free(*lpWideCharStr); *lpWideCharStr = NULL; + status = 0; } - - status = 0; } return status; diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/crypto/crypto.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/crypto/crypto.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/crypto/crypto.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/crypto/crypto.c 2021-02-25 08:51:41.000000000 +0000 @@ -151,7 +151,7 @@ BYTE* pCipherText; size_t cbOut, cbFinal; WINPR_CIPHER_CTX* enc = NULL; - BYTE randomKey[256]; + BYTE randomKey[256] = { 0 }; WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock; if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS) @@ -183,7 +183,7 @@ SecureZeroMemory(randomKey, sizeof(randomKey)); cbOut = pMemBlock->cbData + 16 - 1; - pCipherText = (BYTE*)malloc(cbOut); + pCipherText = (BYTE*)calloc(1, cbOut); if (!pCipherText) goto out; diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/file/generic.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/file/generic.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/file/generic.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/file/generic.c 2021-02-25 08:51:41.000000000 +0000 @@ -361,7 +361,6 @@ WLog_ERR(TAG, "ReadFileEx operation not implemented"); return FALSE; - return TRUE; } BOOL ReadFileScatter(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[], DWORD nNumberOfBytesToRead, diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/nt/ntstatus.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/nt/ntstatus.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/nt/ntstatus.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/nt/ntstatus.c 2021-02-25 08:51:41.000000000 +0000 @@ -1844,7 +1844,11 @@ #if 1 /* Requires sorted struct */ size_t count = ARRAYSIZE(ntstatusmap); size_t base = sizeof(ntstatusmap[0]); - return bsearch(&ntstatus, ntstatusmap, count, base, ntstatus_compare); + const struct ntstatus_map* found = + bsearch(&ntstatus, ntstatusmap, count, base, ntstatus_compare); + if (!found) + return NULL; + return found->tag; #else size_t x; for (x = 0; x < ARRAYSIZE(ntstatusmap); x++) diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/registry/registry.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/registry/registry.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/registry/registry.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/registry/registry.c 2021-02-25 08:51:41.000000000 +0000 @@ -215,7 +215,6 @@ { Reg* reg; RegKey* pKey; - reg = RegGetInstance(); if (!reg) diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/smartcard/smartcard_pcsc.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/smartcard/smartcard_pcsc.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/smartcard/smartcard_pcsc.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/smartcard/smartcard_pcsc.c 2021-02-25 08:51:41.000000000 +0000 @@ -1445,7 +1445,10 @@ { if (!g_PnP_Notification) { - if (0 == _stricmp(rgReaderStates[i].szReader, SMARTCARD_PNP_NOTIFICATION_A)) + LPSCARD_READERSTATEA reader = &rgReaderStates[i]; + if (!reader->szReader) + continue; + if (0 == _stricmp(reader->szReader, SMARTCARD_PNP_NOTIFICATION_A)) { map[i] = -1; /* unmapped */ continue; @@ -1765,45 +1768,6 @@ return SCARD_S_SUCCESS; } -static LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard, LPDWORD pdwState, LPDWORD pdwProtocol, - LPBYTE pbAtr, LPDWORD pcbAtrLen) -{ - PCSC_DWORD cchReaderLen; - SCARDCONTEXT hContext = 0; - LPSTR mszReaderNames = NULL; - PCSC_LONG status = SCARD_S_SUCCESS; - PCSC_SCARDHANDLE* pCard = NULL; - PCSC_DWORD pcsc_dwState = 0; - PCSC_DWORD pcsc_dwProtocol = 0; - PCSC_DWORD pcsc_cbAtrLen = (PCSC_DWORD)*pcbAtrLen; - - if (!g_PCSC.pfnSCardStatus) - return PCSC_SCard_LogError("g_PCSC.pfnSCardStatus"); - - pCard = PCSC_GetCardHandleData(hCard); - - if (!pCard) - return SCARD_E_INVALID_VALUE; - - PCSC_WaitForCardAccess(0, hCard, pCard->shared); - hContext = PCSC_GetCardContextFromHandle(hCard); - - if (!hContext) - return SCARD_E_INVALID_VALUE; - - cchReaderLen = SCARD_AUTOALLOCATE; - status = g_PCSC.pfnSCardStatus(hCard, (LPSTR)&mszReaderNames, &cchReaderLen, &pcsc_dwState, - &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen); - - if (mszReaderNames) - PCSC_SCardFreeMemory_Internal(hContext, mszReaderNames); - - *pdwState = (DWORD)pcsc_dwState; - *pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwProtocol); - *pcbAtrLen = (DWORD)pcsc_cbAtrLen; - return PCSC_MapErrorCodeToWinSCard(status); -} - /* * PCSC returns a string but Windows SCardStatus requires the return to be a multi string. * Therefore extra length checks and additional buffer allocation is required @@ -1979,6 +1943,48 @@ return (LONG)status; } +static LONG WINAPI PCSC_SCardState(SCARDHANDLE hCard, LPDWORD pdwState, LPDWORD pdwProtocol, + LPBYTE pbAtr, LPDWORD pcbAtrLen) +{ + DWORD cchReaderLen; + SCARDCONTEXT hContext = 0; + LPSTR mszReaderNames = NULL; + PCSC_LONG status = SCARD_S_SUCCESS; + PCSC_SCARDHANDLE* pCard = NULL; + DWORD pcsc_dwState = 0; + DWORD pcsc_dwProtocol = 0; + DWORD pcsc_cbAtrLen = 0; + if (pcbAtrLen) + pcsc_cbAtrLen = (PCSC_DWORD)*pcbAtrLen; + + if (!g_PCSC.pfnSCardStatus) + return PCSC_SCard_LogError("g_PCSC.pfnSCardStatus"); + + pCard = PCSC_GetCardHandleData(hCard); + + if (!pCard) + return SCARD_E_INVALID_VALUE; + + PCSC_WaitForCardAccess(0, hCard, pCard->shared); + hContext = PCSC_GetCardContextFromHandle(hCard); + + if (!hContext) + return SCARD_E_INVALID_VALUE; + + cchReaderLen = SCARD_AUTOALLOCATE; + status = PCSC_SCardStatus_Internal(hCard, (LPSTR)&mszReaderNames, &cchReaderLen, &pcsc_dwState, + &pcsc_dwProtocol, pbAtr, &pcsc_cbAtrLen, FALSE); + + if (mszReaderNames) + PCSC_SCardFreeMemory_Internal(hContext, mszReaderNames); + + *pdwState = (DWORD)pcsc_dwState; + *pdwProtocol = PCSC_ConvertProtocolsToWinSCard((DWORD)pcsc_dwProtocol); + if (pcbAtrLen) + *pcbAtrLen = (DWORD)pcsc_cbAtrLen; + return PCSC_MapErrorCodeToWinSCard(status); +} + static LONG WINAPI PCSC_SCardStatusA(SCARDHANDLE hCard, LPSTR mszReaderNames, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) @@ -2206,7 +2212,6 @@ } return PCSC_MapErrorCodeToWinSCard(status); - ; } static LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, @@ -2237,11 +2242,15 @@ if (!hContext) return SCARD_E_INVALID_HANDLE; - if (!pbAttr || !pcbAttrLen) + if (!pcbAttrLen) return SCARD_E_INVALID_PARAMETER; if (*pcbAttrLen == SCARD_AUTOALLOCATE) + { + if (!pbAttr) + return SCARD_E_INVALID_PARAMETER; pcbAttrLenAlloc = TRUE; + } pcsc_cbAttrLen = pcbAttrLenAlloc ? PCSC_SCARD_AUTOALLOCATE : (PCSC_DWORD)*pcbAttrLen; @@ -2252,17 +2261,18 @@ if (status == SCARD_S_SUCCESS) { - *conv.ppb = (BYTE*)calloc(1, pcsc_cbAttrLen); + BYTE* tmp = (BYTE*)calloc(1, pcsc_cbAttrLen); - if (!*conv.ppb) + if (!tmp) return SCARD_E_NO_MEMORY; - status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, *conv.ppb, &pcsc_cbAttrLen); + status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, tmp, &pcsc_cbAttrLen); if (status != SCARD_S_SUCCESS) - free(*conv.ppb); + free(tmp); else - PCSC_AddMemoryBlock(hContext, *conv.ppb); + PCSC_AddMemoryBlock(hContext, tmp); + *conv.ppb = tmp; } } else @@ -2280,12 +2290,10 @@ { size_t length = 0; char* namePCSC = NULL; - DWORD cbAttrLen = 0; char* pbAttrA = NULL; + DWORD cbAttrLen = 0; WCHAR* pbAttrW = NULL; SCARDCONTEXT hContext; - char* friendlyNameA = NULL; - WCHAR* friendlyNameW = NULL; LONG status = SCARD_S_SUCCESS; union { WCHAR** ppw; @@ -2298,6 +2306,8 @@ if (!hContext) return SCARD_E_INVALID_HANDLE; + if (!pcbAttrLen) + return SCARD_E_INVALID_PARAMETER; cbAttrLen = *pcbAttrLen; *pcbAttrLen = SCARD_AUTOALLOCATE; status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A, @@ -2305,7 +2315,6 @@ if (status != SCARD_S_SUCCESS) { - pbAttrA = NULL; *pcbAttrLen = SCARD_AUTOALLOCATE; status = PCSC_SCardGetAttrib_Internal(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W, (LPBYTE)&pbAttrW, pcbAttrLen); @@ -2313,9 +2322,8 @@ if (status != SCARD_S_SUCCESS) return status; - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)pbAttrW, (int)*pcbAttrLen, (char**)&pbAttrA, 0, NULL, - NULL); - namePCSC = pbAttrA; + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)pbAttrW, (int)*pcbAttrLen, (char**)&namePCSC, 0, + NULL, NULL); PCSC_SCardFreeMemory_Internal(hContext, pbAttrW); } else @@ -2329,69 +2337,59 @@ } length = strlen(namePCSC); - friendlyNameA = namePCSC; - namePCSC = NULL; if (dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W) { + WCHAR* friendlyNameW = NULL; /* length here includes null terminator */ - int rc = ConvertToUnicode(CP_UTF8, 0, (char*)friendlyNameA, -1, &friendlyNameW, 0); - free(friendlyNameA); + int rc = ConvertToUnicode(CP_UTF8, 0, (char*)namePCSC, -1, &friendlyNameW, 0); if ((rc < 0) || (!friendlyNameW)) - { - free(namePCSC); - return SCARD_E_NO_MEMORY; - } - length = (size_t)rc; - - if (cbAttrLen == SCARD_AUTOALLOCATE) - { - *conv.ppw = friendlyNameW; - *pcbAttrLen = length * 2; - PCSC_AddMemoryBlock(hContext, *conv.ppb); - } + status = SCARD_E_NO_MEMORY; else { - if ((length * 2) > cbAttrLen) + length = (size_t)rc; + + if (cbAttrLen == SCARD_AUTOALLOCATE) { - free(friendlyNameW); - free(namePCSC); - return SCARD_E_INSUFFICIENT_BUFFER; + *conv.ppw = friendlyNameW; + *pcbAttrLen = length * 2; + PCSC_AddMemoryBlock(hContext, friendlyNameW); } else { - CopyMemory(pbAttr, (BYTE*)friendlyNameW, (length * 2)); - *pcbAttrLen = length * 2; + if ((length * 2) > cbAttrLen) + status = SCARD_E_INSUFFICIENT_BUFFER; + else + { + CopyMemory(pbAttr, (BYTE*)friendlyNameW, (length * 2)); + *pcbAttrLen = length * 2; + } free(friendlyNameW); } } + free(namePCSC); } else { if (cbAttrLen == SCARD_AUTOALLOCATE) { - *conv.ppb = (BYTE*)friendlyNameA; + *conv.ppb = (BYTE*)namePCSC; *pcbAttrLen = length; - PCSC_AddMemoryBlock(hContext, *conv.ppb); + PCSC_AddMemoryBlock(hContext, namePCSC); } else { if ((length + 1) > cbAttrLen) - { - free(friendlyNameA); - free(namePCSC); - return SCARD_E_INSUFFICIENT_BUFFER; - } + status = SCARD_E_INSUFFICIENT_BUFFER; else { - CopyMemory(pbAttr, (BYTE*)friendlyNameA, length + 1); + CopyMemory(pbAttr, namePCSC, length + 1); *pcbAttrLen = length; - free(friendlyNameA); } + free(namePCSC); } } - free(namePCSC); return status; } @@ -2407,12 +2405,18 @@ BYTE** ppb; } conv; + if (NULL == pcbAttrLen) + return SCARD_E_INVALID_PARAMETER; + conv.pb = pbAttr; cbAttrLen = *pcbAttrLen; if (*pcbAttrLen == SCARD_AUTOALLOCATE) { + if (NULL == pbAttr) + return SCARD_E_INVALID_PARAMETER; + pcbAttrLenAlloc = TRUE; *conv.ppb = NULL; } @@ -2444,22 +2448,25 @@ { if (dwAttrId == SCARD_ATTR_VENDOR_NAME) { - const char* vendorName; - - /** - * pcsc-lite adds a null terminator to the vendor name, - * while WinSCard doesn't. Strip the null terminator. - */ - - if (pcbAttrLenAlloc) - vendorName = (char*)*conv.ppb; - else - vendorName = (char*)pbAttr; + if (pbAttr) + { + const char* vendorName; - if (vendorName) - *pcbAttrLen = strlen(vendorName); - else - *pcbAttrLen = 0; + /** + * pcsc-lite adds a null terminator to the vendor name, + * while WinSCard doesn't. Strip the null terminator. + */ + + if (pcbAttrLenAlloc) + vendorName = (char*)*conv.ppb; + else + vendorName = (char*)pbAttr; + + if (vendorName) + *pcbAttrLen = strnlen(vendorName, *pcbAttrLen); + else + *pcbAttrLen = 0; + } } } else @@ -2764,7 +2771,12 @@ { PCSC_CACHE_ITEM* data; PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext); - char* id = card_id_and_name_a(CardIdentifier, LookupName); + char* id; + + if (!ctx) + return SCARD_E_FILE_NOT_FOUND; + + id = card_id_and_name_a(CardIdentifier, LookupName); if (!id) return SCARD_E_NO_MEMORY; @@ -2798,7 +2810,11 @@ { PCSC_CACHE_ITEM* data; PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext); - char* id = card_id_and_name_w(CardIdentifier, LookupName); + char* id; + if (!ctx) + return SCARD_E_FILE_NOT_FOUND; + + id = card_id_and_name_w(CardIdentifier, LookupName); if (!id) return SCARD_E_NO_MEMORY; @@ -2852,7 +2868,9 @@ WINPR_UNUSED(hContext); WINPR_UNUSED(szReaderName); WINPR_UNUSED(pdwDeviceTypeId); - return SCARD_E_UNSUPPORTED_FEATURE; + if (pdwDeviceTypeId) + *pdwDeviceTypeId = SCARD_READER_TYPE_USB; + return SCARD_S_SUCCESS; } static LONG WINAPI PCSC_SCardGetDeviceTypeIdW(SCARDCONTEXT hContext, LPCWSTR szReaderName, @@ -2861,8 +2879,8 @@ WINPR_UNUSED(hContext); WINPR_UNUSED(szReaderName); if (pdwDeviceTypeId) - *pdwDeviceTypeId = 0; - return SCARD_E_UNSUPPORTED_FEATURE; + *pdwDeviceTypeId = SCARD_READER_TYPE_USB; + return SCARD_S_SUCCESS; } static LONG WINAPI PCSC_SCardGetReaderDeviceInstanceIdA(SCARDCONTEXT hContext, LPCSTR szReaderName, diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/smartcard/test/TestSmartCardListReaders.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/smartcard/test/TestSmartCardListReaders.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/smartcard/test/TestSmartCardListReaders.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/smartcard/test/TestSmartCardListReaders.c 2021-02-25 08:51:41.000000000 +0000 @@ -6,10 +6,13 @@ { LONG lStatus; LPSTR pReader; - SCARDCONTEXT hSC; + SCARDCONTEXT hSC = 0; LPSTR mszReaders = NULL; DWORD cchReaders = SCARD_AUTOALLOCATE; + WINPR_UNUSED(argc); + WINPR_UNUSED(argv); + lStatus = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hSC); if (lStatus != SCARD_S_SUCCESS) diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/CredSSP/credssp.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/CredSSP/credssp.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/CredSSP/credssp.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/CredSSP/credssp.c 2021-02-25 08:51:41.000000000 +0000 @@ -27,6 +27,9 @@ #include "credssp.h" #include "../sspi.h" +#include "../log.h" + +#define TAG WINPR_TAG("sspi.CredSSP") static const char* CREDSSP_PACKAGE_NAME = "CredSSP"; @@ -35,6 +38,7 @@ ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -94,6 +98,7 @@ if (!pBuffer) return SEC_E_INSUFFICIENT_MEMORY; + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -102,6 +107,7 @@ void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -127,6 +133,7 @@ return SEC_E_OK; } + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -134,6 +141,7 @@ ULONG ulAttribute, void* pBuffer) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -152,6 +160,7 @@ return SEC_E_OK; } + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -174,6 +183,7 @@ static SECURITY_STATUS SEC_ENTRY credssp_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -181,12 +191,14 @@ PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } static SECURITY_STATUS SEC_ENTRY credssp_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -194,6 +206,7 @@ PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/Kerberos/kerberos.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/Kerberos/kerberos.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/Kerberos/kerberos.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/Kerberos/kerberos.c 2021-02-25 08:51:41.000000000 +0000 @@ -168,6 +168,7 @@ return SEC_E_OK; } + WLog_ERR(TAG, "[%s]: TODO: Implement ulAttribute=%08" PRIx32, __FUNCTION__, ulAttribute); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -183,6 +184,7 @@ ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, PSecBufferDesc pOutput, ULONG* pfContextAttr, PTimeStamp ptsExpiry) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -625,6 +627,7 @@ return SEC_E_OK; } + WLog_ERR(TAG, "[%s]: TODO: Implement ulAttribute=%08" PRIx32, __FUNCTION__, ulAttribute); return SEC_E_UNSUPPORTED_FUNCTION; } diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/Negotiate/negotiate.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/Negotiate/negotiate.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/Negotiate/negotiate.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/Negotiate/negotiate.c 2021-02-25 08:51:41.000000000 +0000 @@ -468,6 +468,7 @@ ULONG ulAttribute, void* pBuffer) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -475,6 +476,7 @@ ULONG ulAttribute, void* pBuffer) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -506,7 +508,8 @@ if (context->sspiW->EncryptMessage) status = context->sspiW->EncryptMessage(&(context->SubContext), fQOP, pMessage, MessageSeqNo); - + else + WLog_WARN(TAG, "[%s] SSPI implementation of function is missing", __FUNCTION__); return status; } @@ -521,7 +524,8 @@ if (context->sspiW->DecryptMessage) status = context->sspiW->DecryptMessage(&(context->SubContext), pMessage, MessageSeqNo, pfQOP); - + else + WLog_WARN(TAG, "[%s] SSPI implementation of function is missing", __FUNCTION__); return status; } @@ -536,7 +540,8 @@ if (context->sspiW->MakeSignature) status = context->sspiW->MakeSignature(&(context->SubContext), fQOP, pMessage, MessageSeqNo); - + else + WLog_WARN(TAG, "[%s] SSPI implementation of function is missing", __FUNCTION__); return status; } @@ -551,7 +556,8 @@ if (context->sspiW->VerifySignature) status = context->sspiW->VerifySignature(&(context->SubContext), pMessage, MessageSeqNo, pfQOP); - + else + WLog_WARN(TAG, "[%s] SSPI implementation of function is missing", __FUNCTION__); return status; } diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/NTLM/ntlm.c 2021-02-25 08:51:41.000000000 +0000 @@ -370,6 +370,7 @@ return SEC_E_OK; } + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -802,6 +803,7 @@ return ntlm_computeMicValue(context, (SecBuffer*)pBuffer); } + WLog_ERR(TAG, "[%s]: TODO: Implement ulAttribute%08" PRIx32, __FUNCTION__, ulAttribute); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -943,6 +945,7 @@ return SEC_E_OK; } + WLog_ERR(TAG, "[%s]: TODO: Implement ulAttribute=%08" PRIx32, __FUNCTION__, ulAttribute); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -1157,6 +1160,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -1164,6 +1168,7 @@ PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) { + WLog_ERR(TAG, "[%s]: TODO: Implement", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; } diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/Schannel/schannel.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/Schannel/schannel.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/Schannel/schannel.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/Schannel/schannel.c 2021-02-25 08:51:41.000000000 +0000 @@ -27,9 +27,12 @@ #include "schannel.h" #include "../sspi.h" +#include "../log.h" static char* SCHANNEL_PACKAGE_NAME = "Schannel"; +#define TAG WINPR_TAG("sspi.Schannel") + SCHANNEL_CONTEXT* schannel_ContextNew(void) { SCHANNEL_CONTEXT* context; @@ -113,6 +116,7 @@ return SEC_E_OK; } + WLog_ERR(TAG, "[%s]: TODO: Implement ulAttribute=%08" PRIx32, __FUNCTION__, ulAttribute); return SEC_E_UNSUPPORTED_FUNCTION; } @@ -308,6 +312,7 @@ return SEC_E_OK; } + WLog_ERR(TAG, "[%s]: TODO: Implement ulAttribute=%08" PRIx32, __FUNCTION__, ulAttribute); return SEC_E_UNSUPPORTED_FUNCTION; } diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/sspi.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/sspi.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/sspi.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/sspi.c 2021-02-25 08:51:41.000000000 +0000 @@ -409,7 +409,7 @@ return "SEC_I_NO_RENEGOTIATION"; } - return "SEC_E_UNKNOWN"; + return NtStatus2Tag(status); } BOOL IsSecurityStatusError(SECURITY_STATUS status) @@ -463,7 +463,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->EnumerateSecurityPackagesW)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->EnumerateSecurityPackagesW(pcPackages, ppPackageInfo); WLog_Print(g_Log, WLOG_DEBUG, "EnumerateSecurityPackagesW: %s (0x%08" PRIX32 ")", @@ -478,7 +482,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiA && g_SspiA->EnumerateSecurityPackagesA)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiA->EnumerateSecurityPackagesA(pcPackages, ppPackageInfo); WLog_Print(g_Log, WLOG_DEBUG, "EnumerateSecurityPackagesA: %s (0x%08" PRIX32 ")", @@ -507,7 +515,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->QuerySecurityPackageInfoW)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->QuerySecurityPackageInfoW(pszPackageName, ppPackageInfo); WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityPackageInfoW: %s (0x%08" PRIX32 ")", @@ -522,7 +534,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiA && g_SspiA->QuerySecurityPackageInfoA)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiA->QuerySecurityPackageInfoA(pszPackageName, ppPackageInfo); WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityPackageInfoA: %s (0x%08" PRIX32 ")", @@ -541,7 +557,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->AcquireCredentialsHandleW)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, @@ -560,7 +580,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiA && g_SspiA->AcquireCredentialsHandleA)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiA->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, @@ -577,7 +601,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->ExportSecurityContext)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->ExportSecurityContext(phContext, fFlags, pPackedContext, pToken); WLog_Print(g_Log, WLOG_DEBUG, "ExportSecurityContext: %s (0x%08" PRIX32 ")", @@ -591,7 +619,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->FreeCredentialsHandle)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->FreeCredentialsHandle(phCredential); WLog_Print(g_Log, WLOG_DEBUG, "FreeCredentialsHandle: %s (0x%08" PRIX32 ")", @@ -607,7 +639,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->ImportSecurityContextW)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext); WLog_Print(g_Log, WLOG_DEBUG, "ImportSecurityContextW: %s (0x%08" PRIX32 ")", @@ -623,7 +659,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiA && g_SspiA->ImportSecurityContextA)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiA->ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext); WLog_Print(g_Log, WLOG_DEBUG, "ImportSecurityContextA: %s (0x%08" PRIX32 ")", @@ -638,7 +678,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->QueryCredentialsAttributesW)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer); WLog_Print(g_Log, WLOG_DEBUG, "QueryCredentialsAttributesW: %s (0x%08" PRIX32 ")", @@ -653,7 +697,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiA && g_SspiA->QueryCredentialsAttributesA)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiA->QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer); WLog_Print(g_Log, WLOG_DEBUG, "QueryCredentialsAttributesA: %s (0x%08" PRIX32 ")", @@ -674,7 +722,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->AcceptSecurityContext)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, TargetDataRep, @@ -690,7 +742,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->ApplyControlToken)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->ApplyControlToken(phContext, pInput); WLog_Print(g_Log, WLOG_DEBUG, "ApplyControlToken: %s (0x%08" PRIX32 ")", @@ -704,7 +760,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->CompleteAuthToken)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->CompleteAuthToken(phContext, pToken); WLog_Print(g_Log, WLOG_DEBUG, "CompleteAuthToken: %s (0x%08" PRIX32 ")", @@ -718,7 +778,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->DeleteSecurityContext)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->DeleteSecurityContext(phContext); WLog_Print(g_Log, WLOG_DEBUG, "DeleteSecurityContext: %s (0x%08" PRIX32 ")", @@ -732,7 +796,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->FreeContextBuffer)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->FreeContextBuffer(pvContextBuffer); WLog_Print(g_Log, WLOG_DEBUG, "FreeContextBuffer: %s (0x%08" PRIX32 ")", @@ -746,7 +814,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->ImpersonateSecurityContext)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->ImpersonateSecurityContext(phContext); WLog_Print(g_Log, WLOG_DEBUG, "ImpersonateSecurityContext: %s (0x%08" PRIX32 ")", @@ -763,7 +835,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->InitializeSecurityContextW)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->InitializeSecurityContextW( phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, @@ -782,7 +858,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiA && g_SspiA->InitializeSecurityContextA)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiA->InitializeSecurityContextA( phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, @@ -799,7 +879,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->QueryContextAttributesW)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->QueryContextAttributesW(phContext, ulAttribute, pBuffer); WLog_Print(g_Log, WLOG_DEBUG, "QueryContextAttributesW: %s (0x%08" PRIX32 ")", @@ -814,7 +898,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiA && g_SspiA->QueryContextAttributesA)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiA->QueryContextAttributesA(phContext, ulAttribute, pBuffer); WLog_Print(g_Log, WLOG_DEBUG, "QueryContextAttributesA: %s (0x%08" PRIX32 ")", @@ -828,7 +916,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->QuerySecurityContextToken)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->QuerySecurityContextToken(phContext, phToken); WLog_Print(g_Log, WLOG_DEBUG, "QuerySecurityContextToken: %s (0x%08" PRIX32 ")", @@ -843,7 +935,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->SetContextAttributesW)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer); WLog_Print(g_Log, WLOG_DEBUG, "SetContextAttributesW: %s (0x%08" PRIX32 ")", @@ -858,7 +954,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiA && g_SspiA->SetContextAttributesA)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiA->SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer); WLog_Print(g_Log, WLOG_DEBUG, "SetContextAttributesA: %s (0x%08" PRIX32 ")", @@ -872,7 +972,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->RevertSecurityContext)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->RevertSecurityContext(phContext); WLog_Print(g_Log, WLOG_DEBUG, "RevertSecurityContext: %s (0x%08" PRIX32 ")", @@ -889,7 +993,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->DecryptMessage)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP); WLog_Print(g_Log, WLOG_DEBUG, "DecryptMessage: %s (0x%08" PRIX32 ")", @@ -904,7 +1012,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->EncryptMessage)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo); WLog_Print(g_Log, WLOG_DEBUG, "EncryptMessage: %s (0x%08" PRIX32 ")", @@ -919,7 +1031,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->MakeSignature)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->MakeSignature(phContext, fQOP, pMessage, MessageSeqNo); WLog_Print(g_Log, WLOG_DEBUG, "MakeSignature: %s (0x%08" PRIX32 ")", @@ -934,7 +1050,11 @@ InitOnceExecuteOnce(&g_Initialized, InitializeSspiModuleInt, NULL, NULL); if (!(g_SspiW && g_SspiW->VerifySignature)) + { + WLog_Print(g_Log, WLOG_WARN, "[%s]: Security module does not provide an implementation", + __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_SspiW->VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP); WLog_Print(g_Log, WLOG_DEBUG, "VerifySignature: %s (0x%08" PRIX32 ")", diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/sspi_gss.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/sspi_gss.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/sspi_gss.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/sspi_gss.c 2021-02-25 08:51:41.000000000 +0000 @@ -165,7 +165,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_acquire_cred)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_acquire_cred(minor_status, desired_name, time_req, desired_mechs, cred_usage, output_cred_handle, actual_mechs, time_rec); @@ -180,7 +183,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_release_cred)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_release_cred(minor_status, cred_handle); WLog_DBG(TAG, "gss_release_cred: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -199,7 +205,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_init_sec_context)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_init_sec_context(minor_status, claimant_cred_handle, context_handle, target_name, mech_type, req_flags, time_req, @@ -221,7 +230,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_accept_sec_context)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_accept_sec_context( minor_status, context_handle, acceptor_cred_handle, input_token_buffer, input_chan_bindings, @@ -239,7 +251,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_process_context_token)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_process_context_token(minor_status, context_handle, token_buffer); WLog_DBG(TAG, "gss_process_context_token: %s (0x%08" PRIX32 ")", @@ -255,7 +270,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_delete_sec_context)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_delete_sec_context(minor_status, context_handle, output_token); WLog_DBG(TAG, "gss_delete_sec_context: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -270,7 +288,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_context_time)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_context_time(minor_status, context_handle, time_rec); WLog_DBG(TAG, "gss_context_time: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -286,7 +307,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_get_mic)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_get_mic(minor_status, context_handle, qop_req, message_buffer, message_token); @@ -302,7 +326,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_verify_mic)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_verify_mic(minor_status, context_handle, message_buffer, message_token, qop_state); @@ -319,7 +346,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_wrap)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_wrap(minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer); @@ -337,7 +367,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_unwrap)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_unwrap(minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, qop_state); @@ -353,7 +386,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_display_status)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_display_status(minor_status, status_value, status_type, mech_type, message_context, status_string); @@ -368,7 +404,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_indicate_mechs)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_indicate_mechs(minor_status, mech_set); WLog_DBG(TAG, "gss_indicate_mechs: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -383,7 +422,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_compare_name)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_compare_name(minor_status, name1, name2, name_equal); WLog_DBG(TAG, "gss_compare_name: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -399,7 +441,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_display_name)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_display_name(minor_status, input_name, output_name_buffer, output_name_type); @@ -415,7 +460,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_import_name)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_import_name(minor_status, input_name_buffer, input_name_type, output_name); @@ -429,7 +477,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_release_name)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_release_name(minor_status, input_name); WLog_DBG(TAG, "gss_release_name: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -443,7 +494,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_release_buffer)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_release_buffer(minor_status, buffer); WLog_DBG(TAG, "gss_release_buffer: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -457,7 +511,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_release_oid_set)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_release_oid_set(minor_status, set); WLog_DBG(TAG, "gss_release_oid_set: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -474,7 +531,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_inquire_cred)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_inquire_cred(minor_status, cred_handle, name, lifetime, cred_usage, mechanisms); @@ -492,7 +552,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_inquire_context)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_inquire_context(minor_status, context_handle, src_name, targ_name, @@ -510,7 +573,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_wrap_size_limit)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_wrap_size_limit(minor_status, context_handle, conf_req_flag, qop_req, req_output_size, max_input_size); @@ -527,7 +593,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_import_name_object)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_import_name_object(minor_status, input_name, input_name_type, output_name); @@ -543,7 +612,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_export_name_object)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_export_name_object(minor_status, input_name, desired_name_type, output_name); @@ -564,7 +636,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_add_cred)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_add_cred( minor_status, input_cred_handle, desired_name, desired_mech, cred_usage, initiator_time_req, @@ -584,7 +659,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_inquire_cred_by_mech)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name, initiator_lifetime, acceptor_lifetime, cred_usage); @@ -601,7 +679,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_export_sec_context)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_export_sec_context(minor_status, context_handle, interprocess_token); WLog_DBG(TAG, "gss_export_sec_context: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -617,7 +698,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_import_sec_context)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_import_sec_context(minor_status, interprocess_token, context_handle); WLog_DBG(TAG, "gss_import_sec_context: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -631,7 +715,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_release_oid)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_release_oid(minor_status, oid); WLog_DBG(TAG, "gss_release_oid: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), status); @@ -644,7 +731,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_create_empty_oid_set)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_create_empty_oid_set(minor_status, oid_set); WLog_DBG(TAG, "gss_create_empty_oid_set: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -659,7 +749,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_add_oid_set_member)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_add_oid_set_member(minor_status, member_oid, oid_set); WLog_DBG(TAG, "gss_add_oid_set_member: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -674,7 +767,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_test_oid_set_member)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_test_oid_set_member(minor_status, member, set, present); WLog_DBG(TAG, "gss_test_oid_set_member: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -689,7 +785,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_str_to_oid)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_str_to_oid(minor_status, oid_str, oid); WLog_DBG(TAG, "gss_str_to_oid: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), status); @@ -703,7 +802,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_oid_to_str)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_oid_to_str(minor_status, oid, oid_str); WLog_DBG(TAG, "gss_oid_to_str: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), status); @@ -717,7 +819,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_inquire_names_for_mech)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_inquire_names_for_mech(minor_status, mechanism, name_types); WLog_DBG(TAG, "gss_inquire_names_for_mech: %s (0x%08" PRIX32 ")", @@ -733,7 +838,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_inquire_mechs_for_name)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_inquire_mechs_for_name(minor_status, input_name, mech_types); WLog_DBG(TAG, "gss_inquire_mechs_for_name: %s (0x%08" PRIX32 ")", @@ -749,7 +857,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_sign)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_sign(minor_status, context_handle, qop_req, message_buffer, message_token); @@ -765,7 +876,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_verify)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_verify(minor_status, context_handle, message_buffer, token_buffer, qop_state); @@ -782,7 +896,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_seal)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_seal(minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer); @@ -799,7 +916,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_unseal)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_unseal(minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, qop_state); @@ -814,7 +934,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_export_name)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_export_name(minor_status, input_name, exported_name); WLog_DBG(TAG, "gss_export_name: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), status); @@ -828,7 +951,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_duplicate_name)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_duplicate_name(minor_status, input_name, dest_name); WLog_DBG(TAG, "gss_duplicate_name: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -845,7 +971,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_canonicalize_name)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_canonicalize_name(minor_status, input_name, mech_type, output_name); WLog_DBG(TAG, "gss_canonicalize_name: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), @@ -861,7 +990,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_pseudo_random)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_pseudo_random(minor_status, context, prf_key, prf_in, desired_output_len, prf_out); @@ -881,7 +1013,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_store_cred)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_store_cred(minor_status, input_cred_handle, input_usage, desired_mech, @@ -897,7 +1032,10 @@ InitOnceExecuteOnce(&g_Initialized, sspi_GssApiInit, NULL, NULL); if (!(g_GssApi && g_GssApi->gss_set_neg_mechs)) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = g_GssApi->gss_set_neg_mechs(minor_status, cred_handle, mech_set); WLog_DBG(TAG, "gss_set_neg_mechs: %s (0x%08" PRIX32 ")", GetSecurityStatusString(status), diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/sspi_winpr.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/sspi_winpr.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/sspi/sspi_winpr.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/sspi/sspi_winpr.c 2021-02-25 08:51:41.000000000 +0000 @@ -794,7 +794,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->AcquireCredentialsHandleW) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, @@ -821,7 +824,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->AcquireCredentialsHandleA) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse, pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, @@ -854,7 +860,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->ExportSecurityContext) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->ExportSecurityContext(phContext, fFlags, pPackedContext, pToken); @@ -883,7 +892,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->FreeCredentialsHandle) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->FreeCredentialsHandle(phCredential); @@ -914,7 +926,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->ImportSecurityContextW) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->ImportSecurityContextW(pszPackage, pPackedContext, pToken, phContext); @@ -945,7 +960,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->ImportSecurityContextA) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->ImportSecurityContextA(pszPackage, pPackedContext, pToken, phContext); @@ -975,7 +993,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->QueryCredentialsAttributesW) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer); @@ -1005,7 +1026,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->QueryCredentialsAttributesA) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->QueryCredentialsAttributesA(phCredential, ulAttribute, pBuffer); @@ -1039,7 +1063,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->AcceptSecurityContext) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, TargetDataRep, @@ -1071,7 +1098,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->ApplyControlToken) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->ApplyControlToken(phContext, pInput); @@ -1101,7 +1131,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->CompleteAuthToken) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->CompleteAuthToken(phContext, pToken); @@ -1130,7 +1163,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->DeleteSecurityContext) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->DeleteSecurityContext(phContext); @@ -1168,7 +1204,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->ImpersonateSecurityContext) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->ImpersonateSecurityContext(phContext); @@ -1200,7 +1239,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->InitializeSecurityContextW) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->InitializeSecurityContextW(phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, @@ -1234,7 +1276,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->InitializeSecurityContextA) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->InitializeSecurityContextA(phCredential, phContext, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, @@ -1266,7 +1311,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->QueryContextAttributesW) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->QueryContextAttributesW(phContext, ulAttribute, pBuffer); @@ -1296,7 +1344,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->QueryContextAttributesA) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->QueryContextAttributesA(phContext, ulAttribute, pBuffer); @@ -1326,7 +1377,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->QuerySecurityContextToken) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->QuerySecurityContextToken(phContext, phToken); @@ -1357,7 +1411,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->SetContextAttributesW) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer); @@ -1388,7 +1445,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->SetContextAttributesA) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->SetContextAttributesA(phContext, ulAttribute, pBuffer, cbBuffer); @@ -1417,7 +1477,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->RevertSecurityContext) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->RevertSecurityContext(phContext); @@ -1450,7 +1513,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->DecryptMessage) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP); @@ -1480,7 +1546,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->EncryptMessage) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo); @@ -1510,7 +1579,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->MakeSignature) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->MakeSignature(phContext, fQOP, pMessage, MessageSeqNo); @@ -1541,7 +1613,10 @@ return SEC_E_SECPKG_NOT_FOUND; if (!table->VerifySignature) + { + WLog_WARN(TAG, "[%s]: Security module does not provide an implementation", __FUNCTION__); return SEC_E_UNSUPPORTED_FUNCTION; + } status = table->VerifySignature(phContext, pMessage, MessageSeqNo, pfQOP); diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/sysinfo/sysinfo.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/sysinfo/sysinfo.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/sysinfo/sysinfo.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/sysinfo/sysinfo.c 2021-02-25 08:51:41.000000000 +0000 @@ -414,7 +414,7 @@ { char* dot; size_t length; - char hostname[256]; + char hostname[256] = { 0 }; if (!lpnSize) { @@ -447,7 +447,7 @@ BOOL GetComputerNameExA(COMPUTER_NAME_FORMAT NameType, LPSTR lpBuffer, LPDWORD lpnSize) { size_t length; - char hostname[256]; + char hostname[256] = { 0 }; if (!lpnSize) { diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/timezone/TimeZones.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/timezone/TimeZones.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/timezone/TimeZones.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/timezone/TimeZones.c 2021-02-25 08:51:41.000000000 +0000 @@ -1,3687 +1,3900 @@ -/* - * Automatically generated with scripts/TimeZones.csx - */ - -#include "TimeZones.h" - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_2[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633032028000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_5[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633032028000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_7[] = { { - 633978108000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633978972000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_9[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633032028000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_11[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_12[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633032028000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_14[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633032028000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_15[] = { { - 633346524000000000ULL, - 0ULL, - 60, - { 0, 3, 6, 2, 22, 0, 0, 0 }, - { 0, 10, 6, 2, 22, 0, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - { 0, 10, 6, 2, 22, 0, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 3, 6, 2, 22, 0, 0, 0 }, - { 0, 10, 6, 2, 22, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 4, 6, 1, 22, 0, 0, 0 }, - { 0, 10, 6, 2, 22, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 5, 6, 1, 22, 0, 0, 0 }, - { 0, 8, 6, 3, 22, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 4, 6, 5, 22, 0, 0, 0 }, - { 0, 9, 6, 1, 22, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 4, 6, 5, 22, 0, 0, 0 }, - { 0, 9, 6, 1, 22, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 4, 6, 5, 22, 0, 0, 0 }, - { 0, 9, 6, 1, 22, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 5, 6, 2, 22, 0, 0, 0 }, - { 0, 8, 6, 2, 22, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 5, 6, 2, 22, 0, 0, 0 }, - { 0, 8, 6, 2, 22, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 5, 6, 2, 22, 0, 0, 0 }, - { 0, 8, 6, 2, 22, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 636818940000000000ULL, - 60, - { 0, 4, 6, 1, 22, 0, 0, 0 }, - { 0, 9, 6, 1, 22, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_16[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_19[] = { { - 635555772000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 1, 4, 1, 0, 0, 0, 0 }, - { 0, 2, 0, 1, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_20[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633032028000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_21[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 4, 6, 1, 23, 59, 59, 999 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 636188220000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_22[] = { { - 632084220000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 1, 0, 0, 0 }, - { 0, 4, 0, 1, 0, 0, 0, 0 }, - }, - { - 632400444000000000ULL, - 632085084000000000ULL, - 60, - { 0, 1, 4, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 0, 0, 0, 0 }, - }, - { - 632715804000000000ULL, - 632401308000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 633031164000000000ULL, - 632716668000000000ULL, - 60, - { 0, 10, 0, 5, 1, 0, 0, 0 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 10, 0, 5, 1, 0, 0, 0 }, - { 0, 3, 0, 2, 0, 0, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 10, 0, 5, 1, 0, 0, 0 }, - { 0, 3, 0, 3, 0, 0, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 10, 0, 5, 1, 0, 0, 0 }, - { 0, 3, 0, 2, 0, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 10, 0, 5, 1, 0, 0, 0 }, - { 0, 3, 0, 2, 0, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 11, 0, 2, 1, 0, 0, 0 }, - { 0, 3, 0, 3, 0, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 11, 0, 1, 1, 0, 0, 0 }, - { 0, 4, 0, 1, 0, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 634925916000000000ULL, - 60, - { 0, 11, 0, 1, 1, 0, 0, 0 }, - { 0, 3, 0, 2, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_23[] = { { - 633031164000000000ULL, - 632716668000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633032028000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_24[] = { { - 635555772000000000ULL, - 0ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 1, 4, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 636818940000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_25[] = { { - 633662748000000000ULL, - 0ULL, - 60, - { 0, 3, 6, 2, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 3, 6, 1, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 4, 6, 2, 23, 59, 59, 999 }, - { 0, 10, 6, 1, 23, 59, 59, 999 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 4, 6, 2, 23, 59, 59, 999 }, - { 0, 10, 6, 1, 23, 59, 59, 999 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 4, 6, 1, 23, 59, 59, 999 }, - { 0, 10, 6, 1, 23, 59, 59, 999 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 3, 6, 4, 23, 59, 59, 999 }, - { 0, 10, 6, 1, 23, 59, 59, 999 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 3, 6, 4, 23, 59, 59, 999 }, - { 0, 10, 6, 1, 23, 59, 59, 999 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 3, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 1, 23, 59, 59, 999 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - { 0, 10, 6, 1, 23, 59, 59, 999 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - { 0, 9, 6, 5, 23, 59, 59, 999 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 3, 6, 4, 23, 59, 59, 999 }, - { 0, 10, 6, 1, 23, 59, 59, 999 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 3, 6, 4, 23, 59, 59, 999 }, - { 0, 10, 6, 1, 23, 59, 59, 999 }, - }, - { - 637449660000000000ULL, - 637134300000000000ULL, - 60, - { 0, 3, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 1, 23, 59, 59, 999 }, - }, - { - 3155378076000000000ULL, - 637450524000000000ULL, - 60, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - { 0, 10, 6, 1, 23, 59, 59, 999 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_26[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633032028000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_27[] = { { - 633346524000000000ULL, - 633032028000000000ULL, - 30, - { 0, 12, 0, 2, 3, 0, 0, 0 }, - { 0, 1, 1, 1, 0, 0, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - -30, - { 0, 5, 0, 1, 2, 30, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_28[] = { { - 632400444000000000ULL, - 0ULL, - 60, - { 0, 1, 4, 1, 0, 0, 0, 0 }, - { 0, 11, 2, 1, 0, 0, 0, 0 }, - }, - { - 632715804000000000ULL, - 632401308000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 0, 3, 0, 0, 0, 0 }, - }, - { - 633031164000000000ULL, - 632716668000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 11, 0, 1, 0, 0, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 2, 6, 5, 23, 59, 59, 999 }, - { 0, 10, 0, 2, 0, 0, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 0, 3, 0, 0, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 2, 6, 2, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 2, 6, 4, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 2, 23, 59, 59, 999 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 11, 6, 1, 23, 59, 59, 999 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 2, 0, 3, 0, 0, 0, 0 }, - { 0, 1, 2, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_30[] = { { - 633346524000000000ULL, - 0ULL, - 60, - { 0, 3, 6, 2, 23, 59, 59, 999 }, - { 0, 10, 6, 2, 23, 59, 59, 999 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - { 0, 10, 6, 2, 23, 59, 59, 999 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 3, 6, 2, 23, 59, 59, 999 }, - { 0, 10, 6, 2, 23, 59, 59, 999 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 4, 6, 1, 23, 59, 59, 999 }, - { 0, 10, 6, 2, 23, 59, 59, 999 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 5, 6, 1, 23, 59, 59, 999 }, - { 0, 8, 6, 3, 23, 59, 59, 999 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 4, 6, 5, 23, 59, 59, 999 }, - { 0, 9, 6, 1, 23, 59, 59, 999 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 4, 6, 5, 23, 59, 59, 999 }, - { 0, 9, 6, 1, 23, 59, 59, 999 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 4, 6, 5, 23, 59, 59, 999 }, - { 0, 9, 6, 1, 23, 59, 59, 999 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 5, 6, 2, 23, 59, 59, 999 }, - { 0, 8, 6, 2, 23, 59, 59, 999 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 5, 6, 2, 23, 59, 59, 999 }, - { 0, 8, 6, 2, 23, 59, 59, 999 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 5, 6, 2, 23, 59, 59, 999 }, - { 0, 8, 6, 2, 23, 59, 59, 999 }, - }, - { - 3155378076000000000ULL, - 636818940000000000ULL, - 60, - { 0, 4, 6, 1, 23, 59, 59, 999 }, - { 0, 9, 6, 1, 23, 59, 59, 999 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_31[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 0, 1, 0, 0 }, - { 0, 4, 0, 1, 0, 1, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 11, 0, 1, 0, 1, 0, 0 }, - { 0, 3, 0, 2, 0, 1, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 11, 0, 1, 0, 1, 0, 0 }, - { 0, 3, 0, 2, 0, 1, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 11, 0, 1, 0, 1, 0, 0 }, - { 0, 3, 0, 2, 0, 1, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 11, 0, 1, 0, 1, 0, 0 }, - { 0, 3, 0, 2, 0, 1, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 0, 1, 0, 0 }, - }, - { - 3155378076000000000ULL, - 634609692000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_32[] = { { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - { 0, 10, 0, 3, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 1, 2, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_33[] = { { - 632400444000000000ULL, - 0ULL, - 60, - { 0, 2, 6, 2, 23, 59, 59, 999 }, - { 0, 11, 2, 1, 0, 0, 0, 0 }, - }, - { - 632715804000000000ULL, - 632401308000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 0, 3, 0, 0, 0, 0 }, - }, - { - 633031164000000000ULL, - 632716668000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 11, 0, 1, 0, 0, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 2, 6, 5, 23, 59, 59, 999 }, - { 0, 10, 0, 2, 0, 0, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 0, 3, 0, 0, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 2, 6, 2, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 2, 6, 4, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 10, 6, 2, 23, 59, 59, 999 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 2, 6, 3, 23, 59, 59, 999 }, - { 0, 11, 6, 1, 23, 59, 59, 999 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 2, 0, 3, 0, 0, 0, 0 }, - { 0, 1, 2, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_35[] = { { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 1, 1, 1, 0, 0, 0, 0 }, - { 0, 12, 0, 5, 0, 0, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 3, 0, 3, 0, 0, 0, 0 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 3, 6, 2, 23, 59, 59, 999 }, - { 0, 1, 4, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_36[] = { { - 632400444000000000ULL, - 0ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 632715804000000000ULL, - 632401308000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 633031164000000000ULL, - 632716668000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 4, 22, 0, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 10, 6, 4, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 4, 22, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 10, 6, 4, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 4, 22, 0, 0, 0 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 637449660000000000ULL, - 637134300000000000ULL, - 60, - { 0, 10, 6, 4, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 637450524000000000ULL, - 60, - { 0, 10, 6, 5, 23, 0, 0, 0 }, - { 0, 3, 6, 5, 22, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_37[] = { { - 635555772000000000ULL, - 0ULL, - 60, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - { 0, 1, 4, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_38[] = { { - 633346524000000000ULL, - 0ULL, - 60, - { 0, 3, 6, 2, 23, 59, 59, 999 }, - { 0, 10, 6, 2, 23, 59, 59, 999 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - { 0, 10, 6, 2, 23, 59, 59, 999 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 3, 6, 2, 23, 59, 59, 999 }, - { 0, 10, 6, 2, 23, 59, 59, 999 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 4, 6, 1, 23, 59, 59, 999 }, - { 0, 10, 6, 2, 23, 59, 59, 999 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 5, 6, 1, 23, 59, 59, 999 }, - { 0, 8, 6, 3, 23, 59, 59, 999 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 4, 6, 5, 23, 59, 59, 999 }, - { 0, 9, 6, 1, 23, 59, 59, 999 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 4, 6, 5, 23, 59, 59, 999 }, - { 0, 9, 6, 1, 23, 59, 59, 999 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 4, 6, 5, 23, 59, 59, 999 }, - { 0, 9, 6, 1, 23, 59, 59, 999 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 5, 6, 2, 23, 59, 59, 999 }, - { 0, 8, 6, 2, 23, 59, 59, 999 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_39[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633032028000000000ULL, - 60, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_40[] = { { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 10, 6, 3, 23, 59, 59, 999 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 2, 6, 4, 23, 59, 59, 999 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_42[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 9, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_43[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 1, 0, 0, 0 }, - { 0, 3, 0, 5, 0, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_46[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 0, 5, 1, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_48[] = { { - 636818076000000000ULL, - 636503580000000000ULL, - -60, - { 0, 1, 1, 1, 1, 0, 0, 0 }, - { 0, 1, 1, 1, 0, 0, 0, 0 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 1, 2, 1, 2, 0, 0, 0 }, - { 0, 1, 2, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_49[] = { { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 8, 0, 5, 23, 59, 59, 999 }, - { 0, 5, 6, 5, 23, 59, 59, 999 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 8, 4, 3, 23, 59, 59, 999 }, - { 0, 5, 0, 5, 23, 59, 59, 999 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 8, 6, 1, 23, 59, 59, 999 }, - { 0, 5, 6, 1, 23, 59, 59, 999 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 7, 6, 5, 23, 59, 59, 999 }, - { 0, 4, 6, 1, 23, 59, 59, 999 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 9, 0, 5, 3, 0, 0, 0 }, - { 0, 4, 0, 5, 2, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 4, 0, 5, 2, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 10, 0, 4, 3, 0, 0, 0 }, - { 0, 3, 0, 4, 2, 0, 0, 0 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 1, 2, 1, 0, 0, 0, 0 }, - { 0, 6, 0, 2, 2, 0, 0, 0 }, - }, - { - 637449660000000000ULL, - 637134300000000000ULL, - 60, - { 0, 4, 0, 3, 3, 0, 0, 0 }, - { 0, 5, 0, 4, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 637450524000000000ULL, - 60, - { 0, 4, 0, 2, 3, 0, 0, 0 }, - { 0, 5, 0, 3, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_50[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_51[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_52[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_53[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_55[] = { { - 634608828000000000ULL, - 0ULL, - 60, - { 0, 10, 5, 5, 1, 0, 0, 0 }, - { 0, 3, 4, 5, 23, 59, 59, 999 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - { 0, 3, 4, 5, 23, 59, 59, 999 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 12, 5, 3, 0, 0, 0, 0 }, - { 0, 1, 2, 1, 0, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 5, 5, 1, 0, 0, 0 }, - { 0, 3, 4, 5, 23, 59, 59, 999 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_56[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 4, 0, 0, 0 }, - { 0, 3, 0, 5, 3, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_57[] = { { - 633978108000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 0, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 4, 23, 59, 59, 999 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 10, 6, 4, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 4, 23, 59, 59, 999 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - }, - { - 637449660000000000ULL, - 637134300000000000ULL, - 60, - { 0, 10, 6, 4, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - }, - { - 3155378076000000000ULL, - 637450524000000000ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 23, 59, 59, 999 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_58[] = { { - 632715804000000000ULL, - 0ULL, - 60, - { 0, 9, 4, 5, 23, 59, 59, 999 }, - { 0, 4, 5, 5, 0, 0, 0, 0 }, - }, - { - 633031164000000000ULL, - 632716668000000000ULL, - 60, - { 0, 9, 4, 3, 23, 59, 59, 999 }, - { 0, 4, 5, 5, 0, 0, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 9, 4, 1, 23, 59, 59, 999 }, - { 0, 4, 4, 5, 23, 59, 59, 999 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 8, 4, 5, 23, 59, 59, 999 }, - { 0, 4, 4, 5, 23, 59, 59, 999 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 8, 4, 3, 23, 59, 59, 999 }, - { 0, 4, 4, 4, 23, 59, 59, 999 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 9, 4, 5, 23, 59, 59, 999 }, - { 0, 4, 4, 5, 23, 59, 59, 999 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 9, 4, 5, 23, 59, 59, 999 }, - { 0, 5, 4, 3, 23, 59, 59, 999 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_59[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_60[] = { { - 632400444000000000ULL, - 0ULL, - 60, - { 0, 9, 4, 5, 23, 59, 59, 999 }, - { 0, 4, 4, 1, 0, 0, 0, 0 }, - }, - { - 632715804000000000ULL, - 632401308000000000ULL, - 60, - { 0, 9, 5, 5, 23, 59, 59, 999 }, - { 0, 4, 5, 1, 0, 0, 0, 0 }, - }, - { - 633031164000000000ULL, - 632716668000000000ULL, - 60, - { 0, 9, 4, 3, 23, 59, 59, 999 }, - { 0, 4, 6, 1, 0, 0, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 11, 4, 1, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 10, 5, 5, 23, 59, 59, 999 }, - { 0, 4, 5, 1, 0, 0, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 10, 4, 5, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 10, 4, 5, 23, 59, 59, 999 }, - { 0, 4, 5, 1, 0, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 10, 4, 5, 23, 59, 59, 999 }, - { 0, 4, 5, 1, 0, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 10, 4, 5, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 10, 4, 4, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 4, 5, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 10, 4, 5, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 10, 4, 5, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 10, 4, 5, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 10, 4, 5, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 10, 4, 4, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 637134300000000000ULL, - 60, - { 0, 10, 4, 5, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_61[] = { { - 634925052000000000ULL, - 0ULL, - 60, - { 0, 9, 5, 3, 1, 0, 0, 0 }, - { 0, 3, 4, 5, 23, 59, 59, 999 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 9, 4, 5, 23, 59, 59, 999 }, - { 0, 3, 4, 5, 23, 59, 59, 999 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 4, 4, 23, 59, 59, 999 }, - { 0, 3, 4, 5, 23, 59, 59, 999 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 10, 4, 4, 23, 59, 59, 999 }, - { 0, 3, 5, 5, 23, 59, 59, 999 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 10, 6, 5, 1, 0, 0, 0 }, - { 0, 3, 6, 5, 1, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 10, 6, 5, 1, 0, 0, 0 }, - { 0, 3, 6, 5, 1, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 10, 6, 5, 1, 0, 0, 0 }, - { 0, 3, 6, 4, 1, 0, 0, 0 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 10, 6, 4, 1, 0, 0, 0 }, - { 0, 3, 5, 5, 0, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 637134300000000000ULL, - 60, - { 0, 10, 6, 5, 1, 0, 0, 0 }, - { 0, 3, 5, 4, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_63[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 4, 0, 0, 0 }, - { 0, 3, 0, 5, 3, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_64[] = { { - 632400444000000000ULL, - 0ULL, - 60, - { 0, 9, 3, 4, 1, 0, 0, 0 }, - { 0, 4, 3, 1, 1, 0, 0, 0 }, - }, - { - 632715804000000000ULL, - 632401308000000000ULL, - 60, - { 0, 10, 0, 2, 2, 0, 0, 0 }, - { 0, 4, 5, 1, 2, 0, 0, 0 }, - }, - { - 633031164000000000ULL, - 632716668000000000ULL, - 60, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 9, 0, 3, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 9, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 9, 0, 2, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - { 0, 4, 5, 1, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 9, 0, 4, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 4, 2, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 4, 2, 0, 0, 0 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 637449660000000000ULL, - 637134300000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 637765020000000000ULL, - 637450524000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 638080380000000000ULL, - 637765884000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 5, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 638081244000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 3, 5, 4, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_65[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_66[] = { { - 636187356000000000ULL, - 0ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 10, 2, 5, 23, 59, 59, 999 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_67[] = { { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 11, 6, 2, 2, 0, 0, 0 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 1, 2, 1, 0, 0, 0, 0 }, - { 0, 3, 5, 5, 1, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_68[] = { { - 636502716000000000ULL, - 0ULL, - 60, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - { 0, 9, 0, 1, 2, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_69[] = { { - 632400444000000000ULL, - 0ULL, - 60, - { 0, 10, 5, 1, 4, 0, 0, 0 }, - { 0, 4, 4, 1, 3, 0, 0, 0 }, - }, - { - 632715804000000000ULL, - 632401308000000000ULL, - 60, - { 0, 10, 6, 1, 4, 0, 0, 0 }, - { 0, 4, 5, 1, 3, 0, 0, 0 }, - }, - { - 633031164000000000ULL, - 632716668000000000ULL, - 60, - { 0, 10, 0, 1, 4, 0, 0, 0 }, - { 0, 4, 6, 1, 3, 0, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 10, 1, 1, 4, 0, 0, 0 }, - { 0, 4, 0, 1, 3, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_70[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 4, 0, 0, 0 }, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 10, 0, 5, 4, 0, 0, 0 }, - { 0, 3, 1, 5, 3, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 10, 0, 5, 4, 0, 0, 0 }, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 10, 0, 5, 4, 0, 0, 0 }, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 4, 0, 0, 0 }, - { 0, 3, 1, 5, 3, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 11, 0, 2, 4, 0, 0, 0 }, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - -60, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_72[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_73[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_75[] = { { - 632400444000000000ULL, - 0ULL, - 60, - { 0, 9, 1, 3, 23, 59, 59, 999 }, - { 0, 3, 0, 3, 0, 0, 0, 0 }, - }, - { - 632715804000000000ULL, - 632401308000000000ULL, - 60, - { 0, 9, 3, 3, 23, 59, 59, 999 }, - { 0, 3, 2, 4, 0, 0, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 9, 6, 3, 23, 59, 59, 999 }, - { 0, 3, 5, 3, 0, 0, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 9, 1, 3, 23, 59, 59, 999 }, - { 0, 3, 0, 4, 0, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 9, 2, 3, 23, 59, 59, 999 }, - { 0, 3, 1, 4, 0, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 9, 3, 3, 23, 59, 59, 999 }, - { 0, 3, 2, 4, 0, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 9, 4, 3, 23, 59, 59, 999 }, - { 0, 3, 3, 3, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 9, 6, 3, 23, 59, 59, 999 }, - { 0, 3, 5, 4, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 9, 0, 3, 23, 59, 59, 999 }, - { 0, 3, 6, 4, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 9, 1, 3, 23, 59, 59, 999 }, - { 0, 3, 0, 4, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 9, 2, 3, 23, 59, 59, 999 }, - { 0, 3, 1, 3, 0, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 9, 4, 3, 23, 59, 59, 999 }, - { 0, 3, 3, 4, 0, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 9, 5, 3, 23, 59, 59, 999 }, - { 0, 3, 4, 4, 0, 0, 0, 0 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 9, 6, 3, 23, 59, 59, 999 }, - { 0, 3, 5, 4, 0, 0, 0, 0 }, - }, - { - 637449660000000000ULL, - 637134300000000000ULL, - 60, - { 0, 9, 0, 3, 23, 59, 59, 999 }, - { 0, 3, 6, 3, 0, 0, 0, 0 }, - }, - { - 637765020000000000ULL, - 637450524000000000ULL, - 60, - { 0, 9, 2, 3, 23, 59, 59, 999 }, - { 0, 3, 1, 4, 0, 0, 0, 0 }, - }, - { - 638080380000000000ULL, - 637765884000000000ULL, - 60, - { 0, 9, 3, 3, 23, 59, 59, 999 }, - { 0, 3, 2, 4, 0, 0, 0, 0 }, - }, - { - 638395740000000000ULL, - 638081244000000000ULL, - 60, - { 0, 9, 4, 3, 23, 59, 59, 999 }, - { 0, 3, 3, 4, 0, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 638396604000000000ULL, - 60, - { 0, 9, 5, 3, 23, 59, 59, 999 }, - { 0, 3, 4, 3, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_77[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - -60, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_78[] = { { - 635871132000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 5, 0, 0, 0 }, - { 0, 3, 0, 5, 4, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_79[] = { { - 633978108000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_80[] = { { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 1, 2, 1, 0, 0, 0, 0 }, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 4, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_81[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - -60, - { 0, 12, 0, 1, 2, 0, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_83[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - -60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 1, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_84[] = { { - 634608828000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_87[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_88[] = { { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 10, 5, 5, 23, 59, 59, 999 }, - { 0, 5, 6, 5, 23, 59, 59, 999 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 10, 6, 5, 23, 59, 59, 999 }, - { 0, 4, 2, 2, 23, 59, 59, 999 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_89[] = { { - 636502716000000000ULL, - 0ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 12, 5, 3, 0, 0, 0, 0 }, - { 0, 1, 1, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_94[] = { { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 12, 4, 5, 23, 59, 59, 999 }, - { 0, 6, 5, 3, 23, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_95[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_98[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - -60, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_99[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 9, 6, 5, 2, 0, 0, 0 }, - { 0, 3, 6, 5, 2, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 9, 5, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 2, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 9, 5, 4, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_100[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_101[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - -60, - { 0, 7, 0, 4, 2, 0, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_102[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - -60, - { 0, 5, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_104[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_106[] = { { - 633031164000000000ULL, - 632716668000000000ULL, - 60, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - { 0, 12, 0, 1, 2, 0, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - }, - { - 633662748000000000ULL, - 633347388000000000ULL, - 60, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - }, - { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - { 0, 1, 4, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_108[] = { { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 9, 5, 5, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 2, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 9, 5, 4, 23, 59, 59, 999 }, - { 0, 3, 6, 5, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_110[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 120, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - -60, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_112[] = { { - 635871132000000000ULL, - 635556636000000000ULL, - 30, - { 0, 8, 5, 2, 23, 59, 59, 999 }, - { 0, 1, 4, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - -30, - { 0, 5, 5, 1, 23, 30, 0, 0 }, - { 0, 1, 1, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_114[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_115[] = { { - 633346524000000000ULL, - 0ULL, - 60, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633347388000000000ULL, - 60, - { 0, 4, 0, 1, 3, 0, 0, 0 }, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_118[] = { { - 633346524000000000ULL, - 0ULL, - 60, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633347388000000000ULL, - 60, - { 0, 4, 0, 1, 3, 0, 0, 0 }, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_120[] = { { - 633346524000000000ULL, - 0ULL, - 60, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633347388000000000ULL, - 60, - { 0, 4, 0, 1, 3, 0, 0, 0 }, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_121[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_122[] = { { - 632715804000000000ULL, - 0ULL, - 30, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - }, - { - 633031164000000000ULL, - 632716668000000000ULL, - 30, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 30, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633347388000000000ULL, - 30, - { 0, 4, 0, 1, 2, 0, 0, 0 }, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_123[] = { { - 635240412000000000ULL, - 0ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - { 0, 12, 0, 5, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_124[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_125[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 120, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - -60, - { 0, 4, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_126[] = { { - 635555772000000000ULL, - 0ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 30, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - { 0, 1, 4, 1, 0, 0, 0, 0 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 1, 2, 1, 0, 0, 0, 0 }, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 637134300000000000ULL, - 60, - { 0, 4, 0, 1, 3, 0, 0, 0 }, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_127[] = { { - 634293468000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 10, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 3, 1, 0, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - -60, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_129[] = { { - 633978108000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 1, 6, 1, 0, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_130[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 3, 0, 3, 3, 0, 0, 0 }, - { 0, 10, 0, 1, 2, 0, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 3, 0, 3, 3, 0, 0, 0 }, - { 0, 9, 0, 5, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633347388000000000ULL, - 60, - { 0, 4, 0, 1, 3, 0, 0, 0 }, - { 0, 9, 0, 5, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_132[] = { { - 633978108000000000ULL, - 633663612000000000ULL, - 60, - { 0, 1, 4, 1, 0, 0, 0, 0 }, - { 0, 11, 0, 5, 2, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 3, 0, 5, 3, 0, 0, 0 }, - { 0, 10, 0, 4, 2, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 3, 0, 1, 3, 0, 0, 0 }, - { 0, 10, 0, 4, 2, 0, 0, 0 }, - }, - { - 634925052000000000ULL, - 634609692000000000ULL, - 60, - { 0, 1, 0, 4, 3, 0, 0, 0 }, - { 0, 10, 0, 3, 2, 0, 0, 0 }, - }, - { - 635240412000000000ULL, - 634925916000000000ULL, - 60, - { 0, 1, 0, 3, 3, 0, 0, 0 }, - { 0, 10, 0, 4, 2, 0, 0, 0 }, - }, - { - 635555772000000000ULL, - 635241276000000000ULL, - 60, - { 0, 1, 0, 3, 2, 0, 0, 0 }, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - }, - { - 635871132000000000ULL, - 635556636000000000ULL, - 60, - { 0, 1, 0, 3, 3, 0, 0, 0 }, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - }, - { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 1, 0, 3, 3, 0, 0, 0 }, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 1, 0, 3, 3, 0, 0, 0 }, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - }, - { - 636818076000000000ULL, - 636503580000000000ULL, - 60, - { 0, 1, 0, 2, 3, 0, 0, 0 }, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - }, - { - 637133436000000000ULL, - 636818940000000000ULL, - 60, - { 0, 1, 0, 2, 3, 0, 0, 0 }, - { 0, 11, 0, 2, 2, 0, 0, 0 }, - }, - { - 637449660000000000ULL, - 637134300000000000ULL, - 60, - { 0, 1, 0, 2, 3, 0, 0, 0 }, - { 0, 11, 0, 2, 2, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 637450524000000000ULL, - 60, - { 0, 1, 0, 3, 3, 0, 0, 0 }, - { 0, 11, 0, 2, 2, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_133[] = { { - 3155378076000000000ULL, - 0ULL, - 60, - { 0, 10, 0, 5, 3, 0, 0, 0 }, - { 0, 3, 0, 5, 2, 0, 0, 0 }, -} }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_134[] = { { - 633031164000000000ULL, - 0ULL, - 60, - { 0, 3, 0, 3, 3, 45, 0, 0 }, - { 0, 10, 0, 1, 2, 45, 0, 0 }, - }, - { - 633346524000000000ULL, - 633032028000000000ULL, - 60, - { 0, 3, 0, 3, 3, 45, 0, 0 }, - { 0, 9, 0, 5, 2, 45, 0, 0 }, - }, - { - 3155378076000000000ULL, - 633347388000000000ULL, - 60, - { 0, 4, 0, 1, 3, 45, 0, 0 }, - { 0, 9, 0, 5, 2, 45, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_136[] = { { - 636187356000000000ULL, - 635871996000000000ULL, - 60, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - { 0, 11, 0, 1, 2, 0, 0, 0 }, - }, - { - 636502716000000000ULL, - 636188220000000000ULL, - 60, - { 0, 1, 0, 3, 3, 0, 0, 0 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - } }; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_137[] = { { - 633978108000000000ULL, - 0ULL, - 0, - { 0, 1, 0, 1, 0, 0, 0, 1 }, - { 0, 1, 0, 1, 0, 0, 0, 0 }, - }, - { - 634293468000000000ULL, - 633978972000000000ULL, - 60, - { 0, 1, 5, 1, 0, 0, 0, 0 }, - { 0, 9, 0, 5, 0, 0, 0, 0 }, - }, - { - 634608828000000000ULL, - 634294332000000000ULL, - 60, - { 0, 4, 6, 1, 4, 0, 0, 0 }, - { 0, 9, 6, 4, 3, 0, 0, 0 }, - }, - { - 3155378076000000000ULL, - 634609692000000000ULL, - 60, - { 0, 4, 0, 1, 4, 0, 0, 0 }, - { 0, 9, 0, 5, 3, 0, 0, 0 }, - } }; - -const TIME_ZONE_ENTRY TimeZoneTable[] = { - { "Dateline Standard Time", 720, FALSE, "(UTC-12:00) International Date Line West", - "Dateline Standard Time", "Dateline Daylight Time", NULL, 0 }, - { "UTC-11", 660, FALSE, "(UTC-11:00) Coordinated Universal Time-11", "UTC-11", "UTC-11", NULL, - 0 }, - { "Aleutian Standard Time", 600, TRUE, "(UTC-10:00) Aleutian Islands", "Aleutian Standard Time", - "Aleutian Daylight Time", TimeZoneRuleTable_2, 2 }, - { "Hawaiian Standard Time", 600, FALSE, "(UTC-10:00) Hawaii", "Hawaiian Standard Time", - "Hawaiian Daylight Time", NULL, 0 }, - { "Marquesas Standard Time", 570, FALSE, "(UTC-09:30) Marquesas Islands", - "Marquesas Standard Time", "Marquesas Daylight Time", NULL, 0 }, - { "Alaskan Standard Time", 540, TRUE, "(UTC-09:00) Alaska", "Alaskan Standard Time", - "Alaskan Daylight Time", TimeZoneRuleTable_5, 2 }, - { "UTC-09", 540, FALSE, "(UTC-09:00) Coordinated Universal Time-09", "UTC-09", "UTC-09", NULL, - 0 }, - { "Pacific Standard Time (Mexico)", 480, TRUE, "(UTC-08:00) Baja California", - "Pacific Standard Time (Mexico)", "Pacific Daylight Time (Mexico)", TimeZoneRuleTable_7, 2 }, - { "UTC-08", 480, FALSE, "(UTC-08:00) Coordinated Universal Time-08", "UTC-08", "UTC-08", NULL, - 0 }, - { "Pacific Standard Time", 480, TRUE, "(UTC-08:00) Pacific Time (US & Canada)", - "Pacific Standard Time", "Pacific Daylight Time", TimeZoneRuleTable_9, 2 }, - { "US Mountain Standard Time", 420, FALSE, "(UTC-07:00) Arizona", "US Mountain Standard Time", - "US Mountain Daylight Time", NULL, 0 }, - { "Mountain Standard Time (Mexico)", 420, TRUE, "(UTC-07:00) Chihuahua, La Paz, Mazatlan", - "Mountain Standard Time (Mexico)", "Mountain Daylight Time (Mexico)", TimeZoneRuleTable_11, - 1 }, - { "Mountain Standard Time", 420, TRUE, "(UTC-07:00) Mountain Time (US & Canada)", - "Mountain Standard Time", "Mountain Daylight Time", TimeZoneRuleTable_12, 2 }, - { "Central America Standard Time", 360, FALSE, "(UTC-06:00) Central America", - "Central America Standard Time", "Central America Daylight Time", NULL, 0 }, - { "Central Standard Time", 360, TRUE, "(UTC-06:00) Central Time (US & Canada)", - "Central Standard Time", "Central Daylight Time", TimeZoneRuleTable_14, 2 }, - { "Easter Island Standard Time", 360, TRUE, "(UTC-06:00) Easter Island", - "Easter Island Standard Time", "Easter Island Daylight Time", TimeZoneRuleTable_15, 13 }, - { "Central Standard Time (Mexico)", 360, TRUE, - "(UTC-06:00) Guadalajara, Mexico City, Monterrey", "Central Standard Time (Mexico)", - "Central Daylight Time (Mexico)", TimeZoneRuleTable_16, 1 }, - { "Canada Central Standard Time", 360, FALSE, "(UTC-06:00) Saskatchewan", - "Canada Central Standard Time", "Canada Central Daylight Time", NULL, 0 }, - { "SA Pacific Standard Time", 300, FALSE, "(UTC-05:00) Bogota, Lima, Quito, Rio Branco", - "SA Pacific Standard Time", "SA Pacific Daylight Time", NULL, 0 }, - { "Eastern Standard Time (Mexico)", 300, TRUE, "(UTC-05:00) Chetumal", - "Eastern Standard Time (Mexico)", "Eastern Daylight Time (Mexico)", TimeZoneRuleTable_19, 2 }, - { "Eastern Standard Time", 300, TRUE, "(UTC-05:00) Eastern Time (US & Canada)", - "Eastern Standard Time", "Eastern Daylight Time", TimeZoneRuleTable_20, 2 }, - { "Haiti Standard Time", 300, TRUE, "(UTC-05:00) Haiti", "Haiti Standard Time", - "Haiti Daylight Time", TimeZoneRuleTable_21, 6 }, - { "Cuba Standard Time", 300, TRUE, "(UTC-05:00) Havana", "Cuba Standard Time", - "Cuba Daylight Time", TimeZoneRuleTable_22, 11 }, - { "US Eastern Standard Time", 300, TRUE, "(UTC-05:00) Indiana (East)", - "US Eastern Standard Time", "US Eastern Daylight Time", TimeZoneRuleTable_23, 2 }, - { "Turks And Caicos Standard Time", 300, TRUE, "(UTC-05:00) Turks and Caicos", - "Turks and Caicos Standard Time", "Turks and Caicos Daylight Time", TimeZoneRuleTable_24, 6 }, - { "Paraguay Standard Time", 240, TRUE, "(UTC-04:00) Asuncion", "Paraguay Standard Time", - "Paraguay Daylight Time", TimeZoneRuleTable_25, 14 }, - { "Atlantic Standard Time", 240, TRUE, "(UTC-04:00) Atlantic Time (Canada)", - "Atlantic Standard Time", "Atlantic Daylight Time", TimeZoneRuleTable_26, 2 }, - { "Venezuela Standard Time", 240, TRUE, "(UTC-04:00) Caracas", "Venezuela Standard Time", - "Venezuela Daylight Time", TimeZoneRuleTable_27, 10 }, - { "Central Brazilian Standard Time", 240, TRUE, "(UTC-04:00) Cuiaba", - "Central Brazilian Standard Time", "Central Brazilian Daylight Time", TimeZoneRuleTable_28, - 16 }, - { "SA Western Standard Time", 240, FALSE, "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", - "SA Western Standard Time", "SA Western Daylight Time", NULL, 0 }, - { "Pacific SA Standard Time", 240, TRUE, "(UTC-04:00) Santiago", "Pacific SA Standard Time", - "Pacific SA Daylight Time", TimeZoneRuleTable_30, 13 }, - { "Newfoundland Standard Time", 210, TRUE, "(UTC-03:30) Newfoundland", - "Newfoundland Standard Time", "Newfoundland Daylight Time", TimeZoneRuleTable_31, 7 }, - { "Tocantins Standard Time", 180, TRUE, "(UTC-03:00) Araguaina", "Tocantins Standard Time", - "Tocantins Daylight Time", TimeZoneRuleTable_32, 2 }, - { "E. South America Standard Time", 180, TRUE, "(UTC-03:00) Brasilia", - "E. South America Standard Time", "E. South America Daylight Time", TimeZoneRuleTable_33, - 16 }, - { "SA Eastern Standard Time", 180, FALSE, "(UTC-03:00) Cayenne, Fortaleza", - "SA Eastern Standard Time", "SA Eastern Daylight Time", NULL, 0 }, - { "Argentina Standard Time", 180, TRUE, "(UTC-03:00) City of Buenos Aires", - "Argentina Standard Time", "Argentina Daylight Time", TimeZoneRuleTable_35, 3 }, - { "Greenland Standard Time", 180, TRUE, "(UTC-03:00) Greenland", "Greenland Standard Time", - "Greenland Daylight Time", TimeZoneRuleTable_36, 18 }, - { "Montevideo Standard Time", 180, TRUE, "(UTC-03:00) Montevideo", "Montevideo Standard Time", - "Montevideo Daylight Time", TimeZoneRuleTable_37, 2 }, - { "Magallanes Standard Time", 180, TRUE, "(UTC-03:00) Punta Arenas", "Magallanes Standard Time", - "Magallanes Daylight Time", TimeZoneRuleTable_38, 9 }, - { "Saint Pierre Standard Time", 180, TRUE, "(UTC-03:00) Saint Pierre and Miquelon", - "Saint Pierre Standard Time", "Saint Pierre Daylight Time", TimeZoneRuleTable_39, 2 }, - { "Bahia Standard Time", 180, TRUE, "(UTC-03:00) Salvador", "Bahia Standard Time", - "Bahia Daylight Time", TimeZoneRuleTable_40, 2 }, - { "UTC-02", 120, FALSE, "(UTC-02:00) Coordinated Universal Time-02", "UTC-02", "UTC-02", NULL, - 0 }, - { "Mid-Atlantic Standard Time", 120, TRUE, "(UTC-02:00) Mid-Atlantic - Old", - "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time", TimeZoneRuleTable_42, 1 }, - { "Azores Standard Time", 60, TRUE, "(UTC-01:00) Azores", "Azores Standard Time", - "Azores Daylight Time", TimeZoneRuleTable_43, 1 }, - { "Cape Verde Standard Time", 60, FALSE, "(UTC-01:00) Cabo Verde Is.", - "Cabo Verde Standard Time", "Cabo Verde Daylight Time", NULL, 0 }, - { "UTC", 0, FALSE, "(UTC) Coordinated Universal Time", "Coordinated Universal Time", - "Coordinated Universal Time", NULL, 0 }, - { "GMT Standard Time", 0, TRUE, "(UTC+00:00) Dublin, Edinburgh, Lisbon, London", - "GMT Standard Time", "GMT Daylight Time", TimeZoneRuleTable_46, 1 }, - { "Greenwich Standard Time", 0, FALSE, "(UTC+00:00) Monrovia, Reykjavik", - "Greenwich Standard Time", "Greenwich Daylight Time", NULL, 0 }, - { "Sao Tome Standard Time", 0, TRUE, "(UTC+00:00) Sao Tome", "Sao Tome Standard Time", - "Sao Tome Daylight Time", TimeZoneRuleTable_48, 2 }, - { "Morocco Standard Time", 0, TRUE, "(UTC+01:00) Casablanca", "Morocco Standard Time", - "Morocco Daylight Time", TimeZoneRuleTable_49, 14 }, - { "W. Europe Standard Time", -60, TRUE, - "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", "W. Europe Standard Time", - "W. Europe Daylight Time", TimeZoneRuleTable_50, 1 }, - { "Central Europe Standard Time", -60, TRUE, - "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", - "Central Europe Standard Time", "Central Europe Daylight Time", TimeZoneRuleTable_51, 1 }, - { "Romance Standard Time", -60, TRUE, "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", - "Romance Standard Time", "Romance Daylight Time", TimeZoneRuleTable_52, 1 }, - { "Central European Standard Time", -60, TRUE, "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", - "Central European Standard Time", "Central European Daylight Time", TimeZoneRuleTable_53, 1 }, - { "W. Central Africa Standard Time", -60, FALSE, "(UTC+01:00) West Central Africa", - "W. Central Africa Standard Time", "W. Central Africa Daylight Time", NULL, 0 }, - { "Jordan Standard Time", -120, TRUE, "(UTC+02:00) Amman", "Jordan Standard Time", - "Jordan Daylight Time", TimeZoneRuleTable_55, 4 }, - { "GTB Standard Time", -120, TRUE, "(UTC+02:00) Athens, Bucharest", "GTB Standard Time", - "GTB Daylight Time", TimeZoneRuleTable_56, 1 }, - { "Middle East Standard Time", -120, TRUE, "(UTC+02:00) Beirut", "Middle East Standard Time", - "Middle East Daylight Time", TimeZoneRuleTable_57, 13 }, - { "Egypt Standard Time", -120, TRUE, "(UTC+02:00) Cairo", "Egypt Standard Time", - "Egypt Daylight Time", TimeZoneRuleTable_58, 7 }, - { "E. Europe Standard Time", -120, TRUE, "(UTC+02:00) Chisinau", "E. Europe Standard Time", - "E. Europe Daylight Time", TimeZoneRuleTable_59, 1 }, - { "Syria Standard Time", -120, TRUE, "(UTC+02:00) Damascus", "Syria Standard Time", - "Syria Daylight Time", TimeZoneRuleTable_60, 17 }, - { "West Bank Standard Time", -120, TRUE, "(UTC+02:00) Gaza, Hebron", - "West Bank Gaza Standard Time", "West Bank Gaza Daylight Time", TimeZoneRuleTable_61, 9 }, - { "South Africa Standard Time", -120, FALSE, "(UTC+02:00) Harare, Pretoria", - "South Africa Standard Time", "South Africa Daylight Time", NULL, 0 }, - { "FLE Standard Time", -120, TRUE, "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", - "FLE Standard Time", "FLE Daylight Time", TimeZoneRuleTable_63, 1 }, - { "Israel Standard Time", -120, TRUE, "(UTC+02:00) Jerusalem", "Jerusalem Standard Time", - "Jerusalem Daylight Time", TimeZoneRuleTable_64, 20 }, - { "Kaliningrad Standard Time", -120, TRUE, "(UTC+02:00) Kaliningrad", - "Russia TZ 1 Standard Time", "Russia TZ 1 Daylight Time", TimeZoneRuleTable_65, 5 }, - { "Sudan Standard Time", -120, TRUE, "(UTC+02:00) Khartoum", "Sudan Standard Time", - "Sudan Daylight Time", TimeZoneRuleTable_66, 2 }, - { "Libya Standard Time", -120, TRUE, "(UTC+02:00) Tripoli", "Libya Standard Time", - "Libya Daylight Time", TimeZoneRuleTable_67, 2 }, - { "Namibia Standard Time", -120, TRUE, "(UTC+02:00) Windhoek", "Namibia Standard Time", - "Namibia Daylight Time", TimeZoneRuleTable_68, 1 }, - { "Arabic Standard Time", -180, TRUE, "(UTC+03:00) Baghdad", "Arabic Standard Time", - "Arabic Daylight Time", TimeZoneRuleTable_69, 4 }, - { "Turkey Standard Time", -180, TRUE, "(UTC+03:00) Istanbul", "Turkey Standard Time", - "Turkey Daylight Time", TimeZoneRuleTable_70, 7 }, - { "Arab Standard Time", -180, FALSE, "(UTC+03:00) Kuwait, Riyadh", "Arab Standard Time", - "Arab Daylight Time", NULL, 0 }, - { "Belarus Standard Time", -180, TRUE, "(UTC+03:00) Minsk", "Belarus Standard Time", - "Belarus Daylight Time", TimeZoneRuleTable_72, 2 }, - { "Russian Standard Time", -180, TRUE, "(UTC+03:00) Moscow, St. Petersburg", - "Russia TZ 2 Standard Time", "Russia TZ 2 Daylight Time", TimeZoneRuleTable_73, 5 }, - { "E. Africa Standard Time", -180, FALSE, "(UTC+03:00) Nairobi", "E. Africa Standard Time", - "E. Africa Daylight Time", NULL, 0 }, - { "Iran Standard Time", -210, TRUE, "(UTC+03:30) Tehran", "Iran Standard Time", - "Iran Daylight Time", TimeZoneRuleTable_75, 19 }, - { "Arabian Standard Time", -240, FALSE, "(UTC+04:00) Abu Dhabi, Muscat", - "Arabian Standard Time", "Arabian Daylight Time", NULL, 0 }, - { "Astrakhan Standard Time", -240, TRUE, "(UTC+04:00) Astrakhan, Ulyanovsk", - "Astrakhan Standard Time", "Astrakhan Daylight Time", TimeZoneRuleTable_77, 5 }, - { "Azerbaijan Standard Time", -240, TRUE, "(UTC+04:00) Baku", "Azerbaijan Standard Time", - "Azerbaijan Daylight Time", TimeZoneRuleTable_78, 1 }, - { "Russia Time Zone 3", -240, TRUE, "(UTC+04:00) Izhevsk, Samara", "Russia TZ 3 Standard Time", - "Russia TZ 3 Daylight Time", TimeZoneRuleTable_79, 3 }, - { "Mauritius Standard Time", -240, TRUE, "(UTC+04:00) Port Louis", "Mauritius Standard Time", - "Mauritius Daylight Time", TimeZoneRuleTable_80, 2 }, - { "Saratov Standard Time", -240, TRUE, "(UTC+04:00) Saratov", "Saratov Standard Time", - "Saratov Daylight Time", TimeZoneRuleTable_81, 5 }, - { "Georgian Standard Time", -240, FALSE, "(UTC+04:00) Tbilisi", "Georgian Standard Time", - "Georgian Daylight Time", NULL, 0 }, - { "Volgograd Standard Time", -240, TRUE, "(UTC+04:00) Volgograd", "Volgograd Standard Time", - "Volgograd Daylight Time", TimeZoneRuleTable_83, 7 }, - { "Caucasus Standard Time", -240, TRUE, "(UTC+04:00) Yerevan", "Caucasus Standard Time", - "Caucasus Daylight Time", TimeZoneRuleTable_84, 1 }, - { "Afghanistan Standard Time", -270, FALSE, "(UTC+04:30) Kabul", "Afghanistan Standard Time", - "Afghanistan Daylight Time", NULL, 0 }, - { "West Asia Standard Time", -300, FALSE, "(UTC+05:00) Ashgabat, Tashkent", - "West Asia Standard Time", "West Asia Daylight Time", NULL, 0 }, - { "Ekaterinburg Standard Time", -300, TRUE, "(UTC+05:00) Ekaterinburg", - "Russia TZ 4 Standard Time", "Russia TZ 4 Daylight Time", TimeZoneRuleTable_87, 5 }, - { "Pakistan Standard Time", -300, TRUE, "(UTC+05:00) Islamabad, Karachi", - "Pakistan Standard Time", "Pakistan Daylight Time", TimeZoneRuleTable_88, 2 }, - { "Qyzylorda Standard Time", -300, TRUE, "(UTC+05:00) Qyzylorda", "Qyzylorda Standard Time", - "Qyzylorda Daylight Time", TimeZoneRuleTable_89, 2 }, - { "India Standard Time", -330, FALSE, "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", - "India Standard Time", "India Daylight Time", NULL, 0 }, - { "Sri Lanka Standard Time", -330, FALSE, "(UTC+05:30) Sri Jayawardenepura", - "Sri Lanka Standard Time", "Sri Lanka Daylight Time", NULL, 0 }, - { "Nepal Standard Time", -345, FALSE, "(UTC+05:45) Kathmandu", "Nepal Standard Time", - "Nepal Daylight Time", NULL, 0 }, - { "Central Asia Standard Time", -360, FALSE, "(UTC+06:00) Astana", "Central Asia Standard Time", - "Central Asia Daylight Time", NULL, 0 }, - { "Bangladesh Standard Time", -360, TRUE, "(UTC+06:00) Dhaka", "Bangladesh Standard Time", - "Bangladesh Daylight Time", TimeZoneRuleTable_94, 1 }, - { "Omsk Standard Time", -360, TRUE, "(UTC+06:00) Omsk", "Omsk Standard Time", - "Omsk Daylight Time", TimeZoneRuleTable_95, 5 }, - { "Myanmar Standard Time", -390, FALSE, "(UTC+06:30) Yangon (Rangoon)", "Myanmar Standard Time", - "Myanmar Daylight Time", NULL, 0 }, - { "SE Asia Standard Time", -420, FALSE, "(UTC+07:00) Bangkok, Hanoi, Jakarta", - "SE Asia Standard Time", "SE Asia Daylight Time", NULL, 0 }, - { "Altai Standard Time", -420, TRUE, "(UTC+07:00) Barnaul, Gorno-Altaysk", - "Altai Standard Time", "Altai Daylight Time", TimeZoneRuleTable_98, 5 }, - { "W. Mongolia Standard Time", -420, TRUE, "(UTC+07:00) Hovd", "W. Mongolia Standard Time", - "W. Mongolia Daylight Time", TimeZoneRuleTable_99, 3 }, - { "North Asia Standard Time", -420, TRUE, "(UTC+07:00) Krasnoyarsk", - "Russia TZ 6 Standard Time", "Russia TZ 6 Daylight Time", TimeZoneRuleTable_100, 5 }, - { "N. Central Asia Standard Time", -420, TRUE, "(UTC+07:00) Novosibirsk", - "Novosibirsk Standard Time", "Novosibirsk Daylight Time", TimeZoneRuleTable_101, 5 }, - { "Tomsk Standard Time", -420, TRUE, "(UTC+07:00) Tomsk", "Tomsk Standard Time", - "Tomsk Daylight Time", TimeZoneRuleTable_102, 5 }, - { "China Standard Time", -480, FALSE, "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", - "China Standard Time", "China Daylight Time", NULL, 0 }, - { "North Asia East Standard Time", -480, TRUE, "(UTC+08:00) Irkutsk", - "Russia TZ 7 Standard Time", "Russia TZ 7 Daylight Time", TimeZoneRuleTable_104, 5 }, - { "Singapore Standard Time", -480, FALSE, "(UTC+08:00) Kuala Lumpur, Singapore", - "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time", NULL, 0 }, - { "W. Australia Standard Time", -480, TRUE, "(UTC+08:00) Perth", "W. Australia Standard Time", - "W. Australia Daylight Time", TimeZoneRuleTable_106, 4 }, - { "Taipei Standard Time", -480, FALSE, "(UTC+08:00) Taipei", "Taipei Standard Time", - "Taipei Daylight Time", NULL, 0 }, - { "Ulaanbaatar Standard Time", -480, TRUE, "(UTC+08:00) Ulaanbaatar", - "Ulaanbaatar Standard Time", "Ulaanbaatar Daylight Time", TimeZoneRuleTable_108, 2 }, - { "Aus Central W. Standard Time", -525, FALSE, "(UTC+08:45) Eucla", - "Aus Central W. Standard Time", "Aus Central W. Daylight Time", NULL, 0 }, - { "Transbaikal Standard Time", -540, TRUE, "(UTC+09:00) Chita", "Transbaikal Standard Time", - "Transbaikal Daylight Time", TimeZoneRuleTable_110, 7 }, - { "Tokyo Standard Time", -540, FALSE, "(UTC+09:00) Osaka, Sapporo, Tokyo", - "Tokyo Standard Time", "Tokyo Daylight Time", NULL, 0 }, - { "North Korea Standard Time", -540, TRUE, "(UTC+09:00) Pyongyang", "North Korea Standard Time", - "North Korea Daylight Time", TimeZoneRuleTable_112, 4 }, - { "Korea Standard Time", -540, FALSE, "(UTC+09:00) Seoul", "Korea Standard Time", - "Korea Daylight Time", NULL, 0 }, - { "Yakutsk Standard Time", -540, TRUE, "(UTC+09:00) Yakutsk", "Russia TZ 8 Standard Time", - "Russia TZ 8 Daylight Time", TimeZoneRuleTable_114, 5 }, - { "Cen. Australia Standard Time", -570, TRUE, "(UTC+09:30) Adelaide", - "Cen. Australia Standard Time", "Cen. Australia Daylight Time", TimeZoneRuleTable_115, 2 }, - { "AUS Central Standard Time", -570, FALSE, "(UTC+09:30) Darwin", "AUS Central Standard Time", - "AUS Central Daylight Time", NULL, 0 }, - { "E. Australia Standard Time", -600, FALSE, "(UTC+10:00) Brisbane", - "E. Australia Standard Time", "E. Australia Daylight Time", NULL, 0 }, - { "AUS Eastern Standard Time", -600, TRUE, "(UTC+10:00) Canberra, Melbourne, Sydney", - "AUS Eastern Standard Time", "AUS Eastern Daylight Time", TimeZoneRuleTable_118, 2 }, - { "West Pacific Standard Time", -600, FALSE, "(UTC+10:00) Guam, Port Moresby", - "West Pacific Standard Time", "West Pacific Daylight Time", NULL, 0 }, - { "Tasmania Standard Time", -600, TRUE, "(UTC+10:00) Hobart", "Tasmania Standard Time", - "Tasmania Daylight Time", TimeZoneRuleTable_120, 2 }, - { "Vladivostok Standard Time", -600, TRUE, "(UTC+10:00) Vladivostok", - "Russia TZ 9 Standard Time", "Russia TZ 9 Daylight Time", TimeZoneRuleTable_121, 5 }, - { "Lord Howe Standard Time", -630, TRUE, "(UTC+10:30) Lord Howe Island", - "Lord Howe Standard Time", "Lord Howe Daylight Time", TimeZoneRuleTable_122, 4 }, - { "Bougainville Standard Time", -660, TRUE, "(UTC+11:00) Bougainville Island", - "Bougainville Standard Time", "Bougainville Daylight Time", TimeZoneRuleTable_123, 2 }, - { "Russia Time Zone 10", -660, TRUE, "(UTC+11:00) Chokurdakh", "Russia TZ 10 Standard Time", - "Russia TZ 10 Daylight Time", TimeZoneRuleTable_124, 5 }, - { "Magadan Standard Time", -660, TRUE, "(UTC+11:00) Magadan", "Magadan Standard Time", - "Magadan Daylight Time", TimeZoneRuleTable_125, 7 }, - { "Norfolk Standard Time", -660, TRUE, "(UTC+11:00) Norfolk Island", "Norfolk Standard Time", - "Norfolk Daylight Time", TimeZoneRuleTable_126, 4 }, - { "Sakhalin Standard Time", -660, TRUE, "(UTC+11:00) Sakhalin", "Sakhalin Standard Time", - "Sakhalin Daylight Time", TimeZoneRuleTable_127, 5 }, - { "Central Pacific Standard Time", -660, FALSE, "(UTC+11:00) Solomon Is., New Caledonia", - "Central Pacific Standard Time", "Central Pacific Daylight Time", NULL, 0 }, - { "Russia Time Zone 11", -720, TRUE, "(UTC+12:00) Anadyr, Petropavlovsk-Kamchatsky", - "Russia TZ 11 Standard Time", "Russia TZ 11 Daylight Time", TimeZoneRuleTable_129, 3 }, - { "New Zealand Standard Time", -720, TRUE, "(UTC+12:00) Auckland, Wellington", - "New Zealand Standard Time", "New Zealand Daylight Time", TimeZoneRuleTable_130, 3 }, - { "UTC+12", -720, FALSE, "(UTC+12:00) Coordinated Universal Time+12", "UTC+12", "UTC+12", NULL, - 0 }, - { "Fiji Standard Time", -720, TRUE, "(UTC+12:00) Fiji", "Fiji Standard Time", - "Fiji Daylight Time", TimeZoneRuleTable_132, 13 }, - { "Kamchatka Standard Time", -720, TRUE, "(UTC+12:00) Petropavlovsk-Kamchatsky - Old", - "Kamchatka Standard Time", "Kamchatka Daylight Time", TimeZoneRuleTable_133, 1 }, - { "Chatham Islands Standard Time", -765, TRUE, "(UTC+12:45) Chatham Islands", - "Chatham Islands Standard Time", "Chatham Islands Daylight Time", TimeZoneRuleTable_134, 3 }, - { "UTC+13", -780, FALSE, "(UTC+13:00) Coordinated Universal Time+13", "UTC+13", "UTC+13", NULL, - 0 }, - { "Tonga Standard Time", -780, TRUE, "(UTC+13:00) Nuku'alofa", "Tonga Standard Time", - "Tonga Daylight Time", TimeZoneRuleTable_136, 2 }, - { "Samoa Standard Time", -780, TRUE, "(UTC+13:00) Samoa", "Samoa Standard Time", - "Samoa Daylight Time", TimeZoneRuleTable_137, 4 }, - { "Line Islands Standard Time", -840, FALSE, "(UTC+14:00) Kiritimati Island", - "Line Islands Standard Time", "Line Islands Daylight Time", NULL, 0 } -}; - -const size_t TimeZoneTableNrElements = ARRAYSIZE(TimeZoneTable); +/* + * Automatically generated with scripts/TimeZones.csx + */ + +#include "TimeZones.h" + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_2[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_5[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_7[] = { { + 633978108000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633978972000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_9[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_11[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_12[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_13[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 637449660000000000ULL, + 637134300000000000ULL, + 60, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_15[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_16[] = { { + 633346524000000000ULL, + 0ULL, + 60, + { 0, 3, 6, 2, 22, 0, 0, 0 }, + { 0, 10, 6, 2, 22, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + { 0, 10, 6, 2, 22, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 3, 6, 2, 22, 0, 0, 0 }, + { 0, 10, 6, 2, 22, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 4, 6, 1, 22, 0, 0, 0 }, + { 0, 10, 6, 2, 22, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 5, 6, 1, 22, 0, 0, 0 }, + { 0, 8, 6, 3, 22, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 4, 6, 5, 22, 0, 0, 0 }, + { 0, 9, 6, 1, 22, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 4, 6, 5, 22, 0, 0, 0 }, + { 0, 9, 6, 1, 22, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 4, 6, 5, 22, 0, 0, 0 }, + { 0, 9, 6, 1, 22, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 5, 6, 2, 22, 0, 0, 0 }, + { 0, 8, 6, 2, 22, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 5, 6, 2, 22, 0, 0, 0 }, + { 0, 8, 6, 2, 22, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 5, 6, 2, 22, 0, 0, 0 }, + { 0, 8, 6, 2, 22, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 636818940000000000ULL, + 60, + { 0, 4, 6, 1, 22, 0, 0, 0 }, + { 0, 9, 6, 1, 22, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_17[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_20[] = { { + 635555772000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 1, 4, 1, 0, 0, 0, 0 }, + { 0, 2, 0, 1, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_21[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_22[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 4, 6, 1, 23, 59, 59, 999 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 636188220000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_23[] = { { + 632084220000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 1, 0, 0, 0 }, + { 0, 4, 0, 1, 0, 0, 0, 0 }, + }, + { + 632400444000000000ULL, + 632085084000000000ULL, + 60, + { 0, 1, 4, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 0, 0, 0, 0 }, + }, + { + 632715804000000000ULL, + 632401308000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 633031164000000000ULL, + 632716668000000000ULL, + 60, + { 0, 10, 0, 5, 1, 0, 0, 0 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 10, 0, 5, 1, 0, 0, 0 }, + { 0, 3, 0, 2, 0, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 10, 0, 5, 1, 0, 0, 0 }, + { 0, 3, 0, 3, 0, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 10, 0, 5, 1, 0, 0, 0 }, + { 0, 3, 0, 2, 0, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 10, 0, 5, 1, 0, 0, 0 }, + { 0, 3, 0, 2, 0, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 11, 0, 2, 1, 0, 0, 0 }, + { 0, 3, 0, 3, 0, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 11, 0, 1, 1, 0, 0, 0 }, + { 0, 4, 0, 1, 0, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 634925916000000000ULL, + 60, + { 0, 11, 0, 1, 1, 0, 0, 0 }, + { 0, 3, 0, 2, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_24[] = { { + 633031164000000000ULL, + 632716668000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_25[] = { { + 635555772000000000ULL, + 0ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 1, 4, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 636818940000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_26[] = { { + 633662748000000000ULL, + 0ULL, + 60, + { 0, 3, 6, 2, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 3, 6, 1, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 4, 6, 2, 23, 59, 59, 999 }, + { 0, 10, 6, 1, 23, 59, 59, 999 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 4, 6, 2, 23, 59, 59, 999 }, + { 0, 10, 6, 1, 23, 59, 59, 999 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 4, 6, 1, 23, 59, 59, 999 }, + { 0, 10, 6, 1, 23, 59, 59, 999 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 3, 6, 4, 23, 59, 59, 999 }, + { 0, 10, 6, 1, 23, 59, 59, 999 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 3, 6, 4, 23, 59, 59, 999 }, + { 0, 10, 6, 1, 23, 59, 59, 999 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 3, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 1, 23, 59, 59, 999 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + { 0, 10, 6, 1, 23, 59, 59, 999 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + { 0, 9, 6, 5, 23, 59, 59, 999 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 3, 6, 4, 23, 59, 59, 999 }, + { 0, 10, 6, 1, 23, 59, 59, 999 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 3, 6, 4, 23, 59, 59, 999 }, + { 0, 10, 6, 1, 23, 59, 59, 999 }, + }, + { + 637449660000000000ULL, + 637134300000000000ULL, + 60, + { 0, 3, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 1, 23, 59, 59, 999 }, + }, + { + 3155378076000000000ULL, + 637450524000000000ULL, + 60, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + { 0, 10, 6, 1, 23, 59, 59, 999 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_27[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_28[] = { { + 633346524000000000ULL, + 633032028000000000ULL, + 30, + { 0, 12, 0, 2, 3, 0, 0, 0 }, + { 0, 1, 1, 1, 0, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + -30, + { 0, 5, 0, 1, 2, 30, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_29[] = { { + 632400444000000000ULL, + 0ULL, + 60, + { 0, 1, 4, 1, 0, 0, 0, 0 }, + { 0, 11, 2, 1, 0, 0, 0, 0 }, + }, + { + 632715804000000000ULL, + 632401308000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 0, 3, 0, 0, 0, 0 }, + }, + { + 633031164000000000ULL, + 632716668000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 11, 0, 1, 0, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 2, 6, 5, 23, 59, 59, 999 }, + { 0, 10, 0, 2, 0, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 0, 3, 0, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 2, 6, 2, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 2, 6, 4, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 2, 23, 59, 59, 999 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 11, 6, 1, 23, 59, 59, 999 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 2, 0, 3, 0, 0, 0, 0 }, + { 0, 1, 2, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_31[] = { { + 633346524000000000ULL, + 0ULL, + 60, + { 0, 3, 6, 2, 23, 59, 59, 999 }, + { 0, 10, 6, 2, 23, 59, 59, 999 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + { 0, 10, 6, 2, 23, 59, 59, 999 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 3, 6, 2, 23, 59, 59, 999 }, + { 0, 10, 6, 2, 23, 59, 59, 999 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 4, 6, 1, 23, 59, 59, 999 }, + { 0, 10, 6, 2, 23, 59, 59, 999 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 5, 6, 1, 23, 59, 59, 999 }, + { 0, 8, 6, 3, 23, 59, 59, 999 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 4, 6, 5, 23, 59, 59, 999 }, + { 0, 9, 6, 1, 23, 59, 59, 999 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 4, 6, 5, 23, 59, 59, 999 }, + { 0, 9, 6, 1, 23, 59, 59, 999 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 4, 6, 5, 23, 59, 59, 999 }, + { 0, 9, 6, 1, 23, 59, 59, 999 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 5, 6, 2, 23, 59, 59, 999 }, + { 0, 8, 6, 2, 23, 59, 59, 999 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 5, 6, 2, 23, 59, 59, 999 }, + { 0, 8, 6, 2, 23, 59, 59, 999 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 5, 6, 2, 23, 59, 59, 999 }, + { 0, 8, 6, 2, 23, 59, 59, 999 }, + }, + { + 3155378076000000000ULL, + 636818940000000000ULL, + 60, + { 0, 4, 6, 1, 23, 59, 59, 999 }, + { 0, 9, 6, 1, 23, 59, 59, 999 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_32[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 0, 1, 0, 0 }, + { 0, 4, 0, 1, 0, 1, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 0, 1, 0, 1, 0, 0 }, + { 0, 3, 0, 2, 0, 1, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 11, 0, 1, 0, 1, 0, 0 }, + { 0, 3, 0, 2, 0, 1, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 11, 0, 1, 0, 1, 0, 0 }, + { 0, 3, 0, 2, 0, 1, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 11, 0, 1, 0, 1, 0, 0 }, + { 0, 3, 0, 2, 0, 1, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 0, 1, 0, 0 }, + }, + { + 3155378076000000000ULL, + 634609692000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_33[] = { { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + { 0, 10, 0, 3, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 1, 2, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_34[] = { { + 632400444000000000ULL, + 0ULL, + 60, + { 0, 2, 6, 2, 23, 59, 59, 999 }, + { 0, 11, 2, 1, 0, 0, 0, 0 }, + }, + { + 632715804000000000ULL, + 632401308000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 0, 3, 0, 0, 0, 0 }, + }, + { + 633031164000000000ULL, + 632716668000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 11, 0, 1, 0, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 2, 6, 5, 23, 59, 59, 999 }, + { 0, 10, 0, 2, 0, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 0, 3, 0, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 2, 6, 2, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 2, 6, 4, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 10, 6, 2, 23, 59, 59, 999 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 2, 6, 3, 23, 59, 59, 999 }, + { 0, 11, 6, 1, 23, 59, 59, 999 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 2, 0, 3, 0, 0, 0, 0 }, + { 0, 1, 2, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_36[] = { { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 1, 1, 1, 0, 0, 0, 0 }, + { 0, 12, 0, 5, 0, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 3, 0, 3, 0, 0, 0, 0 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 3, 6, 2, 23, 59, 59, 999 }, + { 0, 1, 4, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_37[] = { { + 632400444000000000ULL, + 0ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 632715804000000000ULL, + 632401308000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 633031164000000000ULL, + 632716668000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 4, 22, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 10, 6, 4, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 4, 22, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 10, 6, 4, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 4, 22, 0, 0, 0 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 637449660000000000ULL, + 637134300000000000ULL, + 60, + { 0, 10, 6, 4, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 637450524000000000ULL, + 60, + { 0, 10, 6, 5, 23, 0, 0, 0 }, + { 0, 3, 6, 5, 22, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_38[] = { { + 635555772000000000ULL, + 0ULL, + 60, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + { 0, 1, 4, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_39[] = { { + 633346524000000000ULL, + 0ULL, + 60, + { 0, 3, 6, 2, 23, 59, 59, 999 }, + { 0, 10, 6, 2, 23, 59, 59, 999 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + { 0, 10, 6, 2, 23, 59, 59, 999 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 3, 6, 2, 23, 59, 59, 999 }, + { 0, 10, 6, 2, 23, 59, 59, 999 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 4, 6, 1, 23, 59, 59, 999 }, + { 0, 10, 6, 2, 23, 59, 59, 999 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 5, 6, 1, 23, 59, 59, 999 }, + { 0, 8, 6, 3, 23, 59, 59, 999 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 4, 6, 5, 23, 59, 59, 999 }, + { 0, 9, 6, 1, 23, 59, 59, 999 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 4, 6, 5, 23, 59, 59, 999 }, + { 0, 9, 6, 1, 23, 59, 59, 999 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 4, 6, 5, 23, 59, 59, 999 }, + { 0, 9, 6, 1, 23, 59, 59, 999 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 5, 6, 2, 23, 59, 59, 999 }, + { 0, 8, 6, 2, 23, 59, 59, 999 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_40[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_41[] = { { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 10, 6, 3, 23, 59, 59, 999 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 2, 6, 4, 23, 59, 59, 999 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_43[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 9, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_44[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 1, 0, 0, 0 }, + { 0, 3, 0, 5, 0, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_47[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 0, 5, 1, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_49[] = { { + 636818076000000000ULL, + 636503580000000000ULL, + -60, + { 0, 1, 1, 1, 1, 0, 0, 0 }, + { 0, 1, 1, 1, 0, 0, 0, 0 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 1, 2, 1, 2, 0, 0, 0 }, + { 0, 1, 2, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_50[] = { { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 8, 0, 5, 23, 59, 59, 999 }, + { 0, 5, 6, 5, 23, 59, 59, 999 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 8, 4, 3, 23, 59, 59, 999 }, + { 0, 5, 0, 5, 23, 59, 59, 999 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 8, 6, 1, 23, 59, 59, 999 }, + { 0, 5, 6, 1, 23, 59, 59, 999 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 7, 6, 5, 23, 59, 59, 999 }, + { 0, 4, 6, 1, 23, 59, 59, 999 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 9, 0, 5, 3, 0, 0, 0 }, + { 0, 4, 0, 5, 2, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 4, 0, 5, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 10, 0, 4, 3, 0, 0, 0 }, + { 0, 3, 0, 4, 2, 0, 0, 0 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 1, 2, 1, 0, 0, 0, 0 }, + { 0, 6, 0, 2, 2, 0, 0, 0 }, + }, + { + 637449660000000000ULL, + 637134300000000000ULL, + 60, + { 0, 4, 0, 3, 3, 0, 0, 0 }, + { 0, 5, 0, 5, 2, 0, 0, 0 }, + }, + { + 637765020000000000ULL, + 637450524000000000ULL, + 60, + { 0, 4, 0, 2, 3, 0, 0, 0 }, + { 0, 5, 0, 3, 2, 0, 0, 0 }, + }, + { + 638080380000000000ULL, + 637765884000000000ULL, + 60, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + { 0, 5, 0, 2, 2, 0, 0, 0 }, + }, + { + 638395740000000000ULL, + 638081244000000000ULL, + 60, + { 0, 3, 0, 3, 3, 0, 0, 0 }, + { 0, 4, 0, 4, 2, 0, 0, 0 }, + }, + { + 638711964000000000ULL, + 638396604000000000ULL, + 60, + { 0, 3, 0, 2, 3, 0, 0, 0 }, + { 0, 4, 0, 2, 2, 0, 0, 0 }, + }, + { + 639027324000000000ULL, + 638712828000000000ULL, + 60, + { 0, 2, 0, 5, 3, 0, 0, 0 }, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + }, + { + 639342684000000000ULL, + 639028188000000000ULL, + 60, + { 0, 2, 0, 3, 3, 0, 0, 0 }, + { 0, 3, 0, 4, 2, 0, 0, 0 }, + }, + { + 639658044000000000ULL, + 639343548000000000ULL, + 60, + { 0, 2, 0, 1, 3, 0, 0, 0 }, + { 0, 3, 0, 2, 2, 0, 0, 0 }, + }, + { + 639974268000000000ULL, + 639658908000000000ULL, + 60, + { 0, 1, 0, 4, 3, 0, 0, 0 }, + { 0, 3, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 639975132000000000ULL, + 60, + { 0, 1, 0, 2, 3, 0, 0, 0 }, + { 0, 2, 0, 3, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_51[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_52[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_53[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_54[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_56[] = { { + 634608828000000000ULL, + 0ULL, + 60, + { 0, 10, 5, 5, 1, 0, 0, 0 }, + { 0, 3, 4, 5, 23, 59, 59, 999 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + { 0, 3, 4, 5, 23, 59, 59, 999 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 12, 5, 3, 0, 0, 0, 0 }, + { 0, 1, 2, 1, 0, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 5, 5, 1, 0, 0, 0 }, + { 0, 3, 4, 5, 23, 59, 59, 999 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_57[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 4, 0, 0, 0 }, + { 0, 3, 0, 5, 3, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_58[] = { { + 633978108000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 0, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 4, 23, 59, 59, 999 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 10, 6, 4, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 4, 23, 59, 59, 999 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + }, + { + 637449660000000000ULL, + 637134300000000000ULL, + 60, + { 0, 10, 6, 4, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + }, + { + 3155378076000000000ULL, + 637450524000000000ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 23, 59, 59, 999 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_59[] = { { + 632715804000000000ULL, + 0ULL, + 60, + { 0, 9, 4, 5, 23, 59, 59, 999 }, + { 0, 4, 5, 5, 0, 0, 0, 0 }, + }, + { + 633031164000000000ULL, + 632716668000000000ULL, + 60, + { 0, 9, 4, 3, 23, 59, 59, 999 }, + { 0, 4, 5, 5, 0, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 9, 4, 1, 23, 59, 59, 999 }, + { 0, 4, 4, 5, 23, 59, 59, 999 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 8, 4, 5, 23, 59, 59, 999 }, + { 0, 4, 4, 5, 23, 59, 59, 999 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 8, 4, 3, 23, 59, 59, 999 }, + { 0, 4, 4, 4, 23, 59, 59, 999 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 9, 4, 5, 23, 59, 59, 999 }, + { 0, 4, 4, 5, 23, 59, 59, 999 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 9, 4, 5, 23, 59, 59, 999 }, + { 0, 5, 4, 3, 23, 59, 59, 999 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_60[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_61[] = { { + 632400444000000000ULL, + 0ULL, + 60, + { 0, 9, 4, 5, 23, 59, 59, 999 }, + { 0, 4, 4, 1, 0, 0, 0, 0 }, + }, + { + 632715804000000000ULL, + 632401308000000000ULL, + 60, + { 0, 9, 5, 5, 23, 59, 59, 999 }, + { 0, 4, 5, 1, 0, 0, 0, 0 }, + }, + { + 633031164000000000ULL, + 632716668000000000ULL, + 60, + { 0, 9, 4, 3, 23, 59, 59, 999 }, + { 0, 4, 6, 1, 0, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 11, 4, 1, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 10, 5, 5, 23, 59, 59, 999 }, + { 0, 4, 5, 1, 0, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 10, 4, 5, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 10, 4, 5, 23, 59, 59, 999 }, + { 0, 4, 5, 1, 0, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 10, 4, 5, 23, 59, 59, 999 }, + { 0, 4, 5, 1, 0, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 10, 4, 5, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 10, 4, 4, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 4, 5, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 10, 4, 5, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 10, 4, 5, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 10, 4, 5, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 10, 4, 5, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 10, 4, 4, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 637134300000000000ULL, + 60, + { 0, 10, 4, 5, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_62[] = { { + 634925052000000000ULL, + 0ULL, + 60, + { 0, 9, 5, 3, 1, 0, 0, 0 }, + { 0, 3, 4, 5, 23, 59, 59, 999 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 9, 4, 5, 23, 59, 59, 999 }, + { 0, 3, 4, 5, 23, 59, 59, 999 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 4, 4, 23, 59, 59, 999 }, + { 0, 3, 4, 5, 23, 59, 59, 999 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 10, 4, 4, 23, 59, 59, 999 }, + { 0, 3, 5, 5, 23, 59, 59, 999 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 10, 6, 5, 1, 0, 0, 0 }, + { 0, 3, 6, 5, 1, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 10, 6, 5, 1, 0, 0, 0 }, + { 0, 3, 6, 5, 1, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 10, 6, 5, 1, 0, 0, 0 }, + { 0, 3, 6, 4, 1, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 636818940000000000ULL, + 60, + { 0, 10, 6, 5, 1, 0, 0, 0 }, + { 0, 3, 5, 5, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_64[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 4, 0, 0, 0 }, + { 0, 3, 0, 5, 3, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_65[] = { { + 632400444000000000ULL, + 0ULL, + 60, + { 0, 9, 3, 4, 1, 0, 0, 0 }, + { 0, 4, 3, 1, 1, 0, 0, 0 }, + }, + { + 632715804000000000ULL, + 632401308000000000ULL, + 60, + { 0, 10, 0, 2, 2, 0, 0, 0 }, + { 0, 4, 5, 1, 2, 0, 0, 0 }, + }, + { + 633031164000000000ULL, + 632716668000000000ULL, + 60, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 9, 0, 3, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 9, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 9, 0, 2, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + { 0, 4, 5, 1, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 9, 0, 4, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 4, 2, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 4, 2, 0, 0, 0 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 637449660000000000ULL, + 637134300000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 637765020000000000ULL, + 637450524000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 638080380000000000ULL, + 637765884000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 5, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 638081244000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 3, 5, 4, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_66[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_67[] = { { + 636187356000000000ULL, + 0ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 10, 2, 5, 23, 59, 59, 999 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_68[] = { { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 11, 6, 2, 2, 0, 0, 0 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 1, 2, 1, 0, 0, 0, 0 }, + { 0, 3, 5, 5, 1, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_69[] = { { + 636502716000000000ULL, + 0ULL, + 60, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + { 0, 9, 0, 1, 2, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_70[] = { { + 632400444000000000ULL, + 0ULL, + 60, + { 0, 10, 5, 1, 4, 0, 0, 0 }, + { 0, 4, 4, 1, 3, 0, 0, 0 }, + }, + { + 632715804000000000ULL, + 632401308000000000ULL, + 60, + { 0, 10, 6, 1, 4, 0, 0, 0 }, + { 0, 4, 5, 1, 3, 0, 0, 0 }, + }, + { + 633031164000000000ULL, + 632716668000000000ULL, + 60, + { 0, 10, 0, 1, 4, 0, 0, 0 }, + { 0, 4, 6, 1, 3, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 10, 1, 1, 4, 0, 0, 0 }, + { 0, 4, 0, 1, 3, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_71[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 4, 0, 0, 0 }, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 10, 0, 5, 4, 0, 0, 0 }, + { 0, 3, 1, 5, 3, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 10, 0, 5, 4, 0, 0, 0 }, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 10, 0, 5, 4, 0, 0, 0 }, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 4, 0, 0, 0 }, + { 0, 3, 1, 5, 3, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 11, 0, 2, 4, 0, 0, 0 }, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + -60, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_73[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_74[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_76[] = { { + 632400444000000000ULL, + 0ULL, + 60, + { 0, 9, 1, 3, 23, 59, 59, 999 }, + { 0, 3, 0, 3, 0, 0, 0, 0 }, + }, + { + 632715804000000000ULL, + 632401308000000000ULL, + 60, + { 0, 9, 3, 3, 23, 59, 59, 999 }, + { 0, 3, 2, 4, 0, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 9, 6, 3, 23, 59, 59, 999 }, + { 0, 3, 5, 3, 0, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 9, 1, 3, 23, 59, 59, 999 }, + { 0, 3, 0, 4, 0, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 9, 2, 3, 23, 59, 59, 999 }, + { 0, 3, 1, 4, 0, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 9, 3, 3, 23, 59, 59, 999 }, + { 0, 3, 2, 4, 0, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 9, 4, 3, 23, 59, 59, 999 }, + { 0, 3, 3, 3, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 9, 6, 3, 23, 59, 59, 999 }, + { 0, 3, 5, 4, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 9, 0, 3, 23, 59, 59, 999 }, + { 0, 3, 6, 4, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 9, 1, 3, 23, 59, 59, 999 }, + { 0, 3, 0, 4, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 9, 2, 3, 23, 59, 59, 999 }, + { 0, 3, 1, 3, 0, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 9, 4, 3, 23, 59, 59, 999 }, + { 0, 3, 3, 4, 0, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 9, 5, 3, 23, 59, 59, 999 }, + { 0, 3, 4, 4, 0, 0, 0, 0 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 9, 6, 3, 23, 59, 59, 999 }, + { 0, 3, 5, 4, 0, 0, 0, 0 }, + }, + { + 637449660000000000ULL, + 637134300000000000ULL, + 60, + { 0, 9, 0, 3, 23, 59, 59, 999 }, + { 0, 3, 6, 3, 0, 0, 0, 0 }, + }, + { + 637765020000000000ULL, + 637450524000000000ULL, + 60, + { 0, 9, 2, 3, 23, 59, 59, 999 }, + { 0, 3, 1, 4, 0, 0, 0, 0 }, + }, + { + 638080380000000000ULL, + 637765884000000000ULL, + 60, + { 0, 9, 3, 3, 23, 59, 59, 999 }, + { 0, 3, 2, 4, 0, 0, 0, 0 }, + }, + { + 638395740000000000ULL, + 638081244000000000ULL, + 60, + { 0, 9, 4, 3, 23, 59, 59, 999 }, + { 0, 3, 3, 4, 0, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 638396604000000000ULL, + 60, + { 0, 9, 5, 3, 23, 59, 59, 999 }, + { 0, 3, 4, 3, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_78[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + -60, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_79[] = { { + 635871132000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 5, 0, 0, 0 }, + { 0, 3, 0, 5, 4, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_80[] = { { + 633978108000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_81[] = { { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 1, 2, 1, 0, 0, 0, 0 }, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 4, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_82[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + -60, + { 0, 12, 0, 1, 2, 0, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_84[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + -60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 1, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_85[] = { { + 634608828000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_88[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_89[] = { { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 10, 5, 5, 23, 59, 59, 999 }, + { 0, 5, 6, 5, 23, 59, 59, 999 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 10, 6, 5, 23, 59, 59, 999 }, + { 0, 4, 2, 2, 23, 59, 59, 999 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_90[] = { { + 636502716000000000ULL, + 0ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 12, 5, 3, 0, 0, 0, 0 }, + { 0, 1, 1, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_95[] = { { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 12, 4, 5, 23, 59, 59, 999 }, + { 0, 6, 5, 3, 23, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_96[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_99[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + -60, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_100[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 9, 6, 5, 2, 0, 0, 0 }, + { 0, 3, 6, 5, 2, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 9, 5, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 2, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 9, 5, 4, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_101[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_102[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + -60, + { 0, 7, 0, 4, 2, 0, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_103[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + -60, + { 0, 5, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_105[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_107[] = { { + 633031164000000000ULL, + 632716668000000000ULL, + 60, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + { 0, 12, 0, 1, 2, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + }, + { + 633662748000000000ULL, + 633347388000000000ULL, + 60, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + }, + { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + { 0, 1, 4, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_109[] = { { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 9, 5, 5, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 2, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 9, 5, 4, 23, 59, 59, 999 }, + { 0, 3, 6, 5, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_111[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 120, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + -60, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_113[] = { { + 635871132000000000ULL, + 635556636000000000ULL, + 30, + { 0, 8, 5, 2, 23, 59, 59, 999 }, + { 0, 1, 4, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + -30, + { 0, 5, 5, 1, 23, 30, 0, 0 }, + { 0, 1, 1, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_115[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_116[] = { { + 633346524000000000ULL, + 0ULL, + 60, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633347388000000000ULL, + 60, + { 0, 4, 0, 1, 3, 0, 0, 0 }, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_119[] = { { + 633346524000000000ULL, + 0ULL, + 60, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633347388000000000ULL, + 60, + { 0, 4, 0, 1, 3, 0, 0, 0 }, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_121[] = { { + 633346524000000000ULL, + 0ULL, + 60, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633347388000000000ULL, + 60, + { 0, 4, 0, 1, 3, 0, 0, 0 }, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_122[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_123[] = { { + 632715804000000000ULL, + 0ULL, + 30, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + }, + { + 633031164000000000ULL, + 632716668000000000ULL, + 30, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 30, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633347388000000000ULL, + 30, + { 0, 4, 0, 1, 2, 0, 0, 0 }, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_124[] = { { + 635240412000000000ULL, + 0ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + { 0, 12, 0, 5, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_125[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_126[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 120, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + -60, + { 0, 4, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_127[] = { { + 635555772000000000ULL, + 0ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 30, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + { 0, 1, 4, 1, 0, 0, 0, 0 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 1, 2, 1, 0, 0, 0, 0 }, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 637134300000000000ULL, + 60, + { 0, 4, 0, 1, 3, 0, 0, 0 }, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_128[] = { { + 634293468000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 10, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 3, 1, 0, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + -60, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_130[] = { { + 633978108000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 1, 6, 1, 0, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_131[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 3, 0, 3, 3, 0, 0, 0 }, + { 0, 10, 0, 1, 2, 0, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 3, 0, 3, 3, 0, 0, 0 }, + { 0, 9, 0, 5, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633347388000000000ULL, + 60, + { 0, 4, 0, 1, 3, 0, 0, 0 }, + { 0, 9, 0, 5, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_133[] = { { + 633978108000000000ULL, + 633663612000000000ULL, + 60, + { 0, 1, 4, 1, 0, 0, 0, 0 }, + { 0, 11, 0, 5, 2, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 3, 0, 5, 3, 0, 0, 0 }, + { 0, 10, 0, 4, 2, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 3, 0, 1, 3, 0, 0, 0 }, + { 0, 10, 0, 4, 2, 0, 0, 0 }, + }, + { + 634925052000000000ULL, + 634609692000000000ULL, + 60, + { 0, 1, 0, 4, 3, 0, 0, 0 }, + { 0, 10, 0, 3, 2, 0, 0, 0 }, + }, + { + 635240412000000000ULL, + 634925916000000000ULL, + 60, + { 0, 1, 0, 3, 3, 0, 0, 0 }, + { 0, 10, 0, 4, 2, 0, 0, 0 }, + }, + { + 635555772000000000ULL, + 635241276000000000ULL, + 60, + { 0, 1, 0, 3, 2, 0, 0, 0 }, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + }, + { + 635871132000000000ULL, + 635556636000000000ULL, + 60, + { 0, 1, 0, 3, 3, 0, 0, 0 }, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + }, + { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 1, 0, 3, 3, 0, 0, 0 }, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 1, 0, 3, 3, 0, 0, 0 }, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + }, + { + 636818076000000000ULL, + 636503580000000000ULL, + 60, + { 0, 1, 0, 2, 3, 0, 0, 0 }, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + }, + { + 637133436000000000ULL, + 636818940000000000ULL, + 60, + { 0, 1, 0, 2, 3, 0, 0, 0 }, + { 0, 11, 0, 2, 2, 0, 0, 0 }, + }, + { + 637449660000000000ULL, + 637134300000000000ULL, + 60, + { 0, 1, 0, 2, 3, 0, 0, 0 }, + { 0, 11, 0, 2, 2, 0, 0, 0 }, + }, + { + 637765020000000000ULL, + 637450524000000000ULL, + 60, + { 0, 1, 0, 3, 3, 0, 0, 0 }, + { 0, 11, 0, 2, 2, 0, 0, 0 }, + }, + { + 638080380000000000ULL, + 637765884000000000ULL, + 60, + { 0, 1, 0, 3, 3, 0, 0, 0 }, + { 0, 11, 0, 2, 2, 0, 0, 0 }, + }, + { + 638395740000000000ULL, + 638081244000000000ULL, + 60, + { 0, 1, 0, 3, 3, 0, 0, 0 }, + { 0, 11, 0, 2, 2, 0, 0, 0 }, + }, + { + 638711964000000000ULL, + 638396604000000000ULL, + 60, + { 0, 1, 0, 2, 3, 0, 0, 0 }, + { 0, 11, 0, 2, 2, 0, 0, 0 }, + }, + { + 639027324000000000ULL, + 638712828000000000ULL, + 60, + { 0, 1, 0, 2, 3, 0, 0, 0 }, + { 0, 11, 0, 2, 2, 0, 0, 0 }, + }, + { + 639342684000000000ULL, + 639028188000000000ULL, + 60, + { 0, 1, 0, 3, 3, 0, 0, 0 }, + { 0, 11, 0, 2, 2, 0, 0, 0 }, + }, + { + 639658044000000000ULL, + 639343548000000000ULL, + 60, + { 0, 1, 0, 3, 3, 0, 0, 0 }, + { 0, 11, 0, 2, 2, 0, 0, 0 }, + }, + { + 639974268000000000ULL, + 639658908000000000ULL, + 60, + { 0, 1, 0, 3, 3, 0, 0, 0 }, + { 0, 11, 0, 2, 2, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 639975132000000000ULL, + 60, + { 0, 1, 0, 2, 3, 0, 0, 0 }, + { 0, 11, 0, 2, 2, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_134[] = { { + 3155378076000000000ULL, + 0ULL, + 60, + { 0, 10, 0, 5, 3, 0, 0, 0 }, + { 0, 3, 0, 5, 2, 0, 0, 0 }, +} }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_135[] = { { + 633031164000000000ULL, + 0ULL, + 60, + { 0, 3, 0, 3, 3, 45, 0, 0 }, + { 0, 10, 0, 1, 2, 45, 0, 0 }, + }, + { + 633346524000000000ULL, + 633032028000000000ULL, + 60, + { 0, 3, 0, 3, 3, 45, 0, 0 }, + { 0, 9, 0, 5, 2, 45, 0, 0 }, + }, + { + 3155378076000000000ULL, + 633347388000000000ULL, + 60, + { 0, 4, 0, 1, 3, 45, 0, 0 }, + { 0, 9, 0, 5, 2, 45, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_137[] = { { + 636187356000000000ULL, + 635871996000000000ULL, + 60, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + { 0, 11, 0, 1, 2, 0, 0, 0 }, + }, + { + 636502716000000000ULL, + 636188220000000000ULL, + 60, + { 0, 1, 0, 3, 3, 0, 0, 0 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + } }; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_138[] = { { + 633978108000000000ULL, + 0ULL, + 0, + { 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0 }, + }, + { + 634293468000000000ULL, + 633978972000000000ULL, + 60, + { 0, 1, 5, 1, 0, 0, 0, 0 }, + { 0, 9, 0, 5, 0, 0, 0, 0 }, + }, + { + 634608828000000000ULL, + 634294332000000000ULL, + 60, + { 0, 4, 6, 1, 4, 0, 0, 0 }, + { 0, 9, 6, 4, 3, 0, 0, 0 }, + }, + { + 3155378076000000000ULL, + 634609692000000000ULL, + 60, + { 0, 4, 0, 1, 4, 0, 0, 0 }, + { 0, 9, 0, 5, 3, 0, 0, 0 }, + } }; + +const TIME_ZONE_ENTRY TimeZoneTable[] = { + { "Dateline Standard Time", 720, FALSE, "(UTC-12:00) International Date Line West", + "Dateline Standard Time", "Dateline Daylight Time", NULL, 0 }, + { "UTC-11", 660, FALSE, "(UTC-11:00) Coordinated Universal Time-11", "UTC-11", "UTC-11", NULL, + 0 }, + { "Aleutian Standard Time", 600, TRUE, "(UTC-10:00) Aleutian Islands", "Aleutian Standard Time", + "Aleutian Daylight Time", TimeZoneRuleTable_2, 2 }, + { "Hawaiian Standard Time", 600, FALSE, "(UTC-10:00) Hawaii", "Hawaiian Standard Time", + "Hawaiian Daylight Time", NULL, 0 }, + { "Marquesas Standard Time", 570, FALSE, "(UTC-09:30) Marquesas Islands", + "Marquesas Standard Time", "Marquesas Daylight Time", NULL, 0 }, + { "Alaskan Standard Time", 540, TRUE, "(UTC-09:00) Alaska", "Alaskan Standard Time", + "Alaskan Daylight Time", TimeZoneRuleTable_5, 2 }, + { "UTC-09", 540, FALSE, "(UTC-09:00) Coordinated Universal Time-09", "UTC-09", "UTC-09", NULL, + 0 }, + { "Pacific Standard Time (Mexico)", 480, TRUE, "(UTC-08:00) Baja California", + "Pacific Standard Time (Mexico)", "Pacific Daylight Time (Mexico)", TimeZoneRuleTable_7, 2 }, + { "UTC-08", 480, FALSE, "(UTC-08:00) Coordinated Universal Time-08", "UTC-08", "UTC-08", NULL, + 0 }, + { "Pacific Standard Time", 480, TRUE, "(UTC-08:00) Pacific Time (US & Canada)", + "Pacific Standard Time", "Pacific Daylight Time", TimeZoneRuleTable_9, 2 }, + { "US Mountain Standard Time", 420, FALSE, "(UTC-07:00) Arizona", "US Mountain Standard Time", + "US Mountain Daylight Time", NULL, 0 }, + { "Mountain Standard Time (Mexico)", 420, TRUE, "(UTC-07:00) Chihuahua, La Paz, Mazatlan", + "Mountain Standard Time (Mexico)", "Mountain Daylight Time (Mexico)", TimeZoneRuleTable_11, + 1 }, + { "Mountain Standard Time", 420, TRUE, "(UTC-07:00) Mountain Time (US & Canada)", + "Mountain Standard Time", "Mountain Daylight Time", TimeZoneRuleTable_12, 2 }, + { "Yukon Standard Time", 420, TRUE, "(UTC-07:00) Yukon", "Yukon Standard Time", + "Yukon Daylight Time", TimeZoneRuleTable_13, 15 }, + { "Central America Standard Time", 360, FALSE, "(UTC-06:00) Central America", + "Central America Standard Time", "Central America Daylight Time", NULL, 0 }, + { "Central Standard Time", 360, TRUE, "(UTC-06:00) Central Time (US & Canada)", + "Central Standard Time", "Central Daylight Time", TimeZoneRuleTable_15, 2 }, + { "Easter Island Standard Time", 360, TRUE, "(UTC-06:00) Easter Island", + "Easter Island Standard Time", "Easter Island Daylight Time", TimeZoneRuleTable_16, 13 }, + { "Central Standard Time (Mexico)", 360, TRUE, + "(UTC-06:00) Guadalajara, Mexico City, Monterrey", "Central Standard Time (Mexico)", + "Central Daylight Time (Mexico)", TimeZoneRuleTable_17, 1 }, + { "Canada Central Standard Time", 360, FALSE, "(UTC-06:00) Saskatchewan", + "Canada Central Standard Time", "Canada Central Daylight Time", NULL, 0 }, + { "SA Pacific Standard Time", 300, FALSE, "(UTC-05:00) Bogota, Lima, Quito, Rio Branco", + "SA Pacific Standard Time", "SA Pacific Daylight Time", NULL, 0 }, + { "Eastern Standard Time (Mexico)", 300, TRUE, "(UTC-05:00) Chetumal", + "Eastern Standard Time (Mexico)", "Eastern Daylight Time (Mexico)", TimeZoneRuleTable_20, 2 }, + { "Eastern Standard Time", 300, TRUE, "(UTC-05:00) Eastern Time (US & Canada)", + "Eastern Standard Time", "Eastern Daylight Time", TimeZoneRuleTable_21, 2 }, + { "Haiti Standard Time", 300, TRUE, "(UTC-05:00) Haiti", "Haiti Standard Time", + "Haiti Daylight Time", TimeZoneRuleTable_22, 6 }, + { "Cuba Standard Time", 300, TRUE, "(UTC-05:00) Havana", "Cuba Standard Time", + "Cuba Daylight Time", TimeZoneRuleTable_23, 11 }, + { "US Eastern Standard Time", 300, TRUE, "(UTC-05:00) Indiana (East)", + "US Eastern Standard Time", "US Eastern Daylight Time", TimeZoneRuleTable_24, 2 }, + { "Turks And Caicos Standard Time", 300, TRUE, "(UTC-05:00) Turks and Caicos", + "Turks and Caicos Standard Time", "Turks and Caicos Daylight Time", TimeZoneRuleTable_25, 6 }, + { "Paraguay Standard Time", 240, TRUE, "(UTC-04:00) Asuncion", "Paraguay Standard Time", + "Paraguay Daylight Time", TimeZoneRuleTable_26, 14 }, + { "Atlantic Standard Time", 240, TRUE, "(UTC-04:00) Atlantic Time (Canada)", + "Atlantic Standard Time", "Atlantic Daylight Time", TimeZoneRuleTable_27, 2 }, + { "Venezuela Standard Time", 240, TRUE, "(UTC-04:00) Caracas", "Venezuela Standard Time", + "Venezuela Daylight Time", TimeZoneRuleTable_28, 10 }, + { "Central Brazilian Standard Time", 240, TRUE, "(UTC-04:00) Cuiaba", + "Central Brazilian Standard Time", "Central Brazilian Daylight Time", TimeZoneRuleTable_29, + 16 }, + { "SA Western Standard Time", 240, FALSE, "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", + "SA Western Standard Time", "SA Western Daylight Time", NULL, 0 }, + { "Pacific SA Standard Time", 240, TRUE, "(UTC-04:00) Santiago", "Pacific SA Standard Time", + "Pacific SA Daylight Time", TimeZoneRuleTable_31, 13 }, + { "Newfoundland Standard Time", 210, TRUE, "(UTC-03:30) Newfoundland", + "Newfoundland Standard Time", "Newfoundland Daylight Time", TimeZoneRuleTable_32, 7 }, + { "Tocantins Standard Time", 180, TRUE, "(UTC-03:00) Araguaina", "Tocantins Standard Time", + "Tocantins Daylight Time", TimeZoneRuleTable_33, 2 }, + { "E. South America Standard Time", 180, TRUE, "(UTC-03:00) Brasilia", + "E. South America Standard Time", "E. South America Daylight Time", TimeZoneRuleTable_34, + 16 }, + { "SA Eastern Standard Time", 180, FALSE, "(UTC-03:00) Cayenne, Fortaleza", + "SA Eastern Standard Time", "SA Eastern Daylight Time", NULL, 0 }, + { "Argentina Standard Time", 180, TRUE, "(UTC-03:00) City of Buenos Aires", + "Argentina Standard Time", "Argentina Daylight Time", TimeZoneRuleTable_36, 3 }, + { "Greenland Standard Time", 180, TRUE, "(UTC-03:00) Greenland", "Greenland Standard Time", + "Greenland Daylight Time", TimeZoneRuleTable_37, 18 }, + { "Montevideo Standard Time", 180, TRUE, "(UTC-03:00) Montevideo", "Montevideo Standard Time", + "Montevideo Daylight Time", TimeZoneRuleTable_38, 2 }, + { "Magallanes Standard Time", 180, TRUE, "(UTC-03:00) Punta Arenas", "Magallanes Standard Time", + "Magallanes Daylight Time", TimeZoneRuleTable_39, 9 }, + { "Saint Pierre Standard Time", 180, TRUE, "(UTC-03:00) Saint Pierre and Miquelon", + "Saint Pierre Standard Time", "Saint Pierre Daylight Time", TimeZoneRuleTable_40, 2 }, + { "Bahia Standard Time", 180, TRUE, "(UTC-03:00) Salvador", "Bahia Standard Time", + "Bahia Daylight Time", TimeZoneRuleTable_41, 2 }, + { "UTC-02", 120, FALSE, "(UTC-02:00) Coordinated Universal Time-02", "UTC-02", "UTC-02", NULL, + 0 }, + { "Mid-Atlantic Standard Time", 120, TRUE, "(UTC-02:00) Mid-Atlantic - Old", + "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time", TimeZoneRuleTable_43, 1 }, + { "Azores Standard Time", 60, TRUE, "(UTC-01:00) Azores", "Azores Standard Time", + "Azores Daylight Time", TimeZoneRuleTable_44, 1 }, + { "Cape Verde Standard Time", 60, FALSE, "(UTC-01:00) Cabo Verde Is.", + "Cabo Verde Standard Time", "Cabo Verde Daylight Time", NULL, 0 }, + { "UTC", 0, FALSE, "(UTC) Coordinated Universal Time", "Coordinated Universal Time", + "Coordinated Universal Time", NULL, 0 }, + { "GMT Standard Time", 0, TRUE, "(UTC+00:00) Dublin, Edinburgh, Lisbon, London", + "GMT Standard Time", "GMT Daylight Time", TimeZoneRuleTable_47, 1 }, + { "Greenwich Standard Time", 0, FALSE, "(UTC+00:00) Monrovia, Reykjavik", + "Greenwich Standard Time", "Greenwich Daylight Time", NULL, 0 }, + { "Sao Tome Standard Time", 0, TRUE, "(UTC+00:00) Sao Tome", "Sao Tome Standard Time", + "Sao Tome Daylight Time", TimeZoneRuleTable_49, 2 }, + { "Morocco Standard Time", 0, TRUE, "(UTC+01:00) Casablanca", "Morocco Standard Time", + "Morocco Daylight Time", TimeZoneRuleTable_50, 22 }, + { "W. Europe Standard Time", -60, TRUE, + "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", "W. Europe Standard Time", + "W. Europe Daylight Time", TimeZoneRuleTable_51, 1 }, + { "Central Europe Standard Time", -60, TRUE, + "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", + "Central Europe Standard Time", "Central Europe Daylight Time", TimeZoneRuleTable_52, 1 }, + { "Romance Standard Time", -60, TRUE, "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", + "Romance Standard Time", "Romance Daylight Time", TimeZoneRuleTable_53, 1 }, + { "Central European Standard Time", -60, TRUE, "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", + "Central European Standard Time", "Central European Daylight Time", TimeZoneRuleTable_54, 1 }, + { "W. Central Africa Standard Time", -60, FALSE, "(UTC+01:00) West Central Africa", + "W. Central Africa Standard Time", "W. Central Africa Daylight Time", NULL, 0 }, + { "Jordan Standard Time", -120, TRUE, "(UTC+02:00) Amman", "Jordan Standard Time", + "Jordan Daylight Time", TimeZoneRuleTable_56, 4 }, + { "GTB Standard Time", -120, TRUE, "(UTC+02:00) Athens, Bucharest", "GTB Standard Time", + "GTB Daylight Time", TimeZoneRuleTable_57, 1 }, + { "Middle East Standard Time", -120, TRUE, "(UTC+02:00) Beirut", "Middle East Standard Time", + "Middle East Daylight Time", TimeZoneRuleTable_58, 13 }, + { "Egypt Standard Time", -120, TRUE, "(UTC+02:00) Cairo", "Egypt Standard Time", + "Egypt Daylight Time", TimeZoneRuleTable_59, 7 }, + { "E. Europe Standard Time", -120, TRUE, "(UTC+02:00) Chisinau", "E. Europe Standard Time", + "E. Europe Daylight Time", TimeZoneRuleTable_60, 1 }, + { "Syria Standard Time", -120, TRUE, "(UTC+02:00) Damascus", "Syria Standard Time", + "Syria Daylight Time", TimeZoneRuleTable_61, 17 }, + { "West Bank Standard Time", -120, TRUE, "(UTC+02:00) Gaza, Hebron", + "West Bank Gaza Standard Time", "West Bank Gaza Daylight Time", TimeZoneRuleTable_62, 8 }, + { "South Africa Standard Time", -120, FALSE, "(UTC+02:00) Harare, Pretoria", + "South Africa Standard Time", "South Africa Daylight Time", NULL, 0 }, + { "FLE Standard Time", -120, TRUE, "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", + "FLE Standard Time", "FLE Daylight Time", TimeZoneRuleTable_64, 1 }, + { "Israel Standard Time", -120, TRUE, "(UTC+02:00) Jerusalem", "Jerusalem Standard Time", + "Jerusalem Daylight Time", TimeZoneRuleTable_65, 20 }, + { "Kaliningrad Standard Time", -120, TRUE, "(UTC+02:00) Kaliningrad", + "Russia TZ 1 Standard Time", "Russia TZ 1 Daylight Time", TimeZoneRuleTable_66, 5 }, + { "Sudan Standard Time", -120, TRUE, "(UTC+02:00) Khartoum", "Sudan Standard Time", + "Sudan Daylight Time", TimeZoneRuleTable_67, 2 }, + { "Libya Standard Time", -120, TRUE, "(UTC+02:00) Tripoli", "Libya Standard Time", + "Libya Daylight Time", TimeZoneRuleTable_68, 2 }, + { "Namibia Standard Time", -120, TRUE, "(UTC+02:00) Windhoek", "Namibia Standard Time", + "Namibia Daylight Time", TimeZoneRuleTable_69, 1 }, + { "Arabic Standard Time", -180, TRUE, "(UTC+03:00) Baghdad", "Arabic Standard Time", + "Arabic Daylight Time", TimeZoneRuleTable_70, 4 }, + { "Turkey Standard Time", -180, TRUE, "(UTC+03:00) Istanbul", "Turkey Standard Time", + "Turkey Daylight Time", TimeZoneRuleTable_71, 7 }, + { "Arab Standard Time", -180, FALSE, "(UTC+03:00) Kuwait, Riyadh", "Arab Standard Time", + "Arab Daylight Time", NULL, 0 }, + { "Belarus Standard Time", -180, TRUE, "(UTC+03:00) Minsk", "Belarus Standard Time", + "Belarus Daylight Time", TimeZoneRuleTable_73, 2 }, + { "Russian Standard Time", -180, TRUE, "(UTC+03:00) Moscow, St. Petersburg", + "Russia TZ 2 Standard Time", "Russia TZ 2 Daylight Time", TimeZoneRuleTable_74, 5 }, + { "E. Africa Standard Time", -180, FALSE, "(UTC+03:00) Nairobi", "E. Africa Standard Time", + "E. Africa Daylight Time", NULL, 0 }, + { "Iran Standard Time", -210, TRUE, "(UTC+03:30) Tehran", "Iran Standard Time", + "Iran Daylight Time", TimeZoneRuleTable_76, 19 }, + { "Arabian Standard Time", -240, FALSE, "(UTC+04:00) Abu Dhabi, Muscat", + "Arabian Standard Time", "Arabian Daylight Time", NULL, 0 }, + { "Astrakhan Standard Time", -240, TRUE, "(UTC+04:00) Astrakhan, Ulyanovsk", + "Astrakhan Standard Time", "Astrakhan Daylight Time", TimeZoneRuleTable_78, 5 }, + { "Azerbaijan Standard Time", -240, TRUE, "(UTC+04:00) Baku", "Azerbaijan Standard Time", + "Azerbaijan Daylight Time", TimeZoneRuleTable_79, 1 }, + { "Russia Time Zone 3", -240, TRUE, "(UTC+04:00) Izhevsk, Samara", "Russia TZ 3 Standard Time", + "Russia TZ 3 Daylight Time", TimeZoneRuleTable_80, 3 }, + { "Mauritius Standard Time", -240, TRUE, "(UTC+04:00) Port Louis", "Mauritius Standard Time", + "Mauritius Daylight Time", TimeZoneRuleTable_81, 2 }, + { "Saratov Standard Time", -240, TRUE, "(UTC+04:00) Saratov", "Saratov Standard Time", + "Saratov Daylight Time", TimeZoneRuleTable_82, 5 }, + { "Georgian Standard Time", -240, FALSE, "(UTC+04:00) Tbilisi", "Georgian Standard Time", + "Georgian Daylight Time", NULL, 0 }, + { "Volgograd Standard Time", -240, TRUE, "(UTC+04:00) Volgograd", "Volgograd Standard Time", + "Volgograd Daylight Time", TimeZoneRuleTable_84, 7 }, + { "Caucasus Standard Time", -240, TRUE, "(UTC+04:00) Yerevan", "Caucasus Standard Time", + "Caucasus Daylight Time", TimeZoneRuleTable_85, 1 }, + { "Afghanistan Standard Time", -270, FALSE, "(UTC+04:30) Kabul", "Afghanistan Standard Time", + "Afghanistan Daylight Time", NULL, 0 }, + { "West Asia Standard Time", -300, FALSE, "(UTC+05:00) Ashgabat, Tashkent", + "West Asia Standard Time", "West Asia Daylight Time", NULL, 0 }, + { "Ekaterinburg Standard Time", -300, TRUE, "(UTC+05:00) Ekaterinburg", + "Russia TZ 4 Standard Time", "Russia TZ 4 Daylight Time", TimeZoneRuleTable_88, 5 }, + { "Pakistan Standard Time", -300, TRUE, "(UTC+05:00) Islamabad, Karachi", + "Pakistan Standard Time", "Pakistan Daylight Time", TimeZoneRuleTable_89, 2 }, + { "Qyzylorda Standard Time", -300, TRUE, "(UTC+05:00) Qyzylorda", "Qyzylorda Standard Time", + "Qyzylorda Daylight Time", TimeZoneRuleTable_90, 2 }, + { "India Standard Time", -330, FALSE, "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", + "India Standard Time", "India Daylight Time", NULL, 0 }, + { "Sri Lanka Standard Time", -330, FALSE, "(UTC+05:30) Sri Jayawardenepura", + "Sri Lanka Standard Time", "Sri Lanka Daylight Time", NULL, 0 }, + { "Nepal Standard Time", -345, FALSE, "(UTC+05:45) Kathmandu", "Nepal Standard Time", + "Nepal Daylight Time", NULL, 0 }, + { "Central Asia Standard Time", -360, FALSE, "(UTC+06:00) Astana", "Central Asia Standard Time", + "Central Asia Daylight Time", NULL, 0 }, + { "Bangladesh Standard Time", -360, TRUE, "(UTC+06:00) Dhaka", "Bangladesh Standard Time", + "Bangladesh Daylight Time", TimeZoneRuleTable_95, 1 }, + { "Omsk Standard Time", -360, TRUE, "(UTC+06:00) Omsk", "Omsk Standard Time", + "Omsk Daylight Time", TimeZoneRuleTable_96, 5 }, + { "Myanmar Standard Time", -390, FALSE, "(UTC+06:30) Yangon (Rangoon)", "Myanmar Standard Time", + "Myanmar Daylight Time", NULL, 0 }, + { "SE Asia Standard Time", -420, FALSE, "(UTC+07:00) Bangkok, Hanoi, Jakarta", + "SE Asia Standard Time", "SE Asia Daylight Time", NULL, 0 }, + { "Altai Standard Time", -420, TRUE, "(UTC+07:00) Barnaul, Gorno-Altaysk", + "Altai Standard Time", "Altai Daylight Time", TimeZoneRuleTable_99, 5 }, + { "W. Mongolia Standard Time", -420, TRUE, "(UTC+07:00) Hovd", "W. Mongolia Standard Time", + "W. Mongolia Daylight Time", TimeZoneRuleTable_100, 3 }, + { "North Asia Standard Time", -420, TRUE, "(UTC+07:00) Krasnoyarsk", + "Russia TZ 6 Standard Time", "Russia TZ 6 Daylight Time", TimeZoneRuleTable_101, 5 }, + { "N. Central Asia Standard Time", -420, TRUE, "(UTC+07:00) Novosibirsk", + "Novosibirsk Standard Time", "Novosibirsk Daylight Time", TimeZoneRuleTable_102, 5 }, + { "Tomsk Standard Time", -420, TRUE, "(UTC+07:00) Tomsk", "Tomsk Standard Time", + "Tomsk Daylight Time", TimeZoneRuleTable_103, 5 }, + { "China Standard Time", -480, FALSE, "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", + "China Standard Time", "China Daylight Time", NULL, 0 }, + { "North Asia East Standard Time", -480, TRUE, "(UTC+08:00) Irkutsk", + "Russia TZ 7 Standard Time", "Russia TZ 7 Daylight Time", TimeZoneRuleTable_105, 5 }, + { "Singapore Standard Time", -480, FALSE, "(UTC+08:00) Kuala Lumpur, Singapore", + "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time", NULL, 0 }, + { "W. Australia Standard Time", -480, TRUE, "(UTC+08:00) Perth", "W. Australia Standard Time", + "W. Australia Daylight Time", TimeZoneRuleTable_107, 4 }, + { "Taipei Standard Time", -480, FALSE, "(UTC+08:00) Taipei", "Taipei Standard Time", + "Taipei Daylight Time", NULL, 0 }, + { "Ulaanbaatar Standard Time", -480, TRUE, "(UTC+08:00) Ulaanbaatar", + "Ulaanbaatar Standard Time", "Ulaanbaatar Daylight Time", TimeZoneRuleTable_109, 2 }, + { "Aus Central W. Standard Time", -525, FALSE, "(UTC+08:45) Eucla", + "Aus Central W. Standard Time", "Aus Central W. Daylight Time", NULL, 0 }, + { "Transbaikal Standard Time", -540, TRUE, "(UTC+09:00) Chita", "Transbaikal Standard Time", + "Transbaikal Daylight Time", TimeZoneRuleTable_111, 7 }, + { "Tokyo Standard Time", -540, FALSE, "(UTC+09:00) Osaka, Sapporo, Tokyo", + "Tokyo Standard Time", "Tokyo Daylight Time", NULL, 0 }, + { "North Korea Standard Time", -540, TRUE, "(UTC+09:00) Pyongyang", "North Korea Standard Time", + "North Korea Daylight Time", TimeZoneRuleTable_113, 4 }, + { "Korea Standard Time", -540, FALSE, "(UTC+09:00) Seoul", "Korea Standard Time", + "Korea Daylight Time", NULL, 0 }, + { "Yakutsk Standard Time", -540, TRUE, "(UTC+09:00) Yakutsk", "Russia TZ 8 Standard Time", + "Russia TZ 8 Daylight Time", TimeZoneRuleTable_115, 5 }, + { "Cen. Australia Standard Time", -570, TRUE, "(UTC+09:30) Adelaide", + "Cen. Australia Standard Time", "Cen. Australia Daylight Time", TimeZoneRuleTable_116, 2 }, + { "AUS Central Standard Time", -570, FALSE, "(UTC+09:30) Darwin", "AUS Central Standard Time", + "AUS Central Daylight Time", NULL, 0 }, + { "E. Australia Standard Time", -600, FALSE, "(UTC+10:00) Brisbane", + "E. Australia Standard Time", "E. Australia Daylight Time", NULL, 0 }, + { "AUS Eastern Standard Time", -600, TRUE, "(UTC+10:00) Canberra, Melbourne, Sydney", + "AUS Eastern Standard Time", "AUS Eastern Daylight Time", TimeZoneRuleTable_119, 2 }, + { "West Pacific Standard Time", -600, FALSE, "(UTC+10:00) Guam, Port Moresby", + "West Pacific Standard Time", "West Pacific Daylight Time", NULL, 0 }, + { "Tasmania Standard Time", -600, TRUE, "(UTC+10:00) Hobart", "Tasmania Standard Time", + "Tasmania Daylight Time", TimeZoneRuleTable_121, 2 }, + { "Vladivostok Standard Time", -600, TRUE, "(UTC+10:00) Vladivostok", + "Russia TZ 9 Standard Time", "Russia TZ 9 Daylight Time", TimeZoneRuleTable_122, 5 }, + { "Lord Howe Standard Time", -630, TRUE, "(UTC+10:30) Lord Howe Island", + "Lord Howe Standard Time", "Lord Howe Daylight Time", TimeZoneRuleTable_123, 4 }, + { "Bougainville Standard Time", -660, TRUE, "(UTC+11:00) Bougainville Island", + "Bougainville Standard Time", "Bougainville Daylight Time", TimeZoneRuleTable_124, 2 }, + { "Russia Time Zone 10", -660, TRUE, "(UTC+11:00) Chokurdakh", "Russia TZ 10 Standard Time", + "Russia TZ 10 Daylight Time", TimeZoneRuleTable_125, 5 }, + { "Magadan Standard Time", -660, TRUE, "(UTC+11:00) Magadan", "Magadan Standard Time", + "Magadan Daylight Time", TimeZoneRuleTable_126, 7 }, + { "Norfolk Standard Time", -660, TRUE, "(UTC+11:00) Norfolk Island", "Norfolk Standard Time", + "Norfolk Daylight Time", TimeZoneRuleTable_127, 4 }, + { "Sakhalin Standard Time", -660, TRUE, "(UTC+11:00) Sakhalin", "Sakhalin Standard Time", + "Sakhalin Daylight Time", TimeZoneRuleTable_128, 5 }, + { "Central Pacific Standard Time", -660, FALSE, "(UTC+11:00) Solomon Is., New Caledonia", + "Central Pacific Standard Time", "Central Pacific Daylight Time", NULL, 0 }, + { "Russia Time Zone 11", -720, TRUE, "(UTC+12:00) Anadyr, Petropavlovsk-Kamchatsky", + "Russia TZ 11 Standard Time", "Russia TZ 11 Daylight Time", TimeZoneRuleTable_130, 3 }, + { "New Zealand Standard Time", -720, TRUE, "(UTC+12:00) Auckland, Wellington", + "New Zealand Standard Time", "New Zealand Daylight Time", TimeZoneRuleTable_131, 3 }, + { "UTC+12", -720, FALSE, "(UTC+12:00) Coordinated Universal Time+12", "UTC+12", "UTC+12", NULL, + 0 }, + { "Fiji Standard Time", -720, TRUE, "(UTC+12:00) Fiji", "Fiji Standard Time", + "Fiji Daylight Time", TimeZoneRuleTable_133, 21 }, + { "Kamchatka Standard Time", -720, TRUE, "(UTC+12:00) Petropavlovsk-Kamchatsky - Old", + "Kamchatka Standard Time", "Kamchatka Daylight Time", TimeZoneRuleTable_134, 1 }, + { "Chatham Islands Standard Time", -765, TRUE, "(UTC+12:45) Chatham Islands", + "Chatham Islands Standard Time", "Chatham Islands Daylight Time", TimeZoneRuleTable_135, 3 }, + { "UTC+13", -780, FALSE, "(UTC+13:00) Coordinated Universal Time+13", "UTC+13", "UTC+13", NULL, + 0 }, + { "Tonga Standard Time", -780, TRUE, "(UTC+13:00) Nuku'alofa", "Tonga Standard Time", + "Tonga Daylight Time", TimeZoneRuleTable_137, 2 }, + { "Samoa Standard Time", -780, TRUE, "(UTC+13:00) Samoa", "Samoa Standard Time", + "Samoa Daylight Time", TimeZoneRuleTable_138, 4 }, + { "Line Islands Standard Time", -840, FALSE, "(UTC+14:00) Kiritimati Island", + "Line Islands Standard Time", "Line Islands Daylight Time", NULL, 0 } +}; + +const size_t TimeZoneTableNrElements = ARRAYSIZE(TimeZoneTable); diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/cmdline.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/utils/cmdline.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/cmdline.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/utils/cmdline.c 2021-02-25 08:51:41.000000000 +0000 @@ -312,7 +312,8 @@ if (value) { - if (options[j].Flags & (COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_VALUE_BOOL)) + if (!(options[j].Flags & + (COMMAND_LINE_VALUE_OPTIONAL | COMMAND_LINE_VALUE_REQUIRED))) { log_error(flags, "Failed at index %d [%s]: Unexpected value", i, argv[i]); return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/collections/StreamPool.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/utils/collections/StreamPool.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/collections/StreamPool.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/utils/collections/StreamPool.c 2021-02-25 08:51:41.000000000 +0000 @@ -201,6 +201,9 @@ void StreamPool_Return(wStreamPool* pool, wStream* s) { + if (!s) + return; + if (pool->synchronized) EnterCriticalSection(&pool->lock); diff -Nru freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/image.c freerdp2-2.3.0+dfsg1/winpr/libwinpr/utils/image.c --- freerdp2-2.2.0+dfsg1/winpr/libwinpr/utils/image.c 2020-07-20 13:38:46.000000000 +0000 +++ freerdp2-2.3.0+dfsg1/winpr/libwinpr/utils/image.c 2021-02-25 08:51:41.000000000 +0000 @@ -163,7 +163,7 @@ bmp_header = winpr_bitmap_construct_header(width, height, bpp); if (!bmp_header) - return -1; + goto fail; if (fwrite(bmp_header, WINPR_IMAGE_BMP_HEADER_LEN, 1, fp) != 1 || fwrite((void*)data, img_size, 1, fp) != 1)