diff --git a/CMakeLists.txt b/CMakeLists.txt index cdca0a0..45affd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,9 +34,9 @@ if(NOT DEFINED FREERDP_VENDOR) set(FREERDP_VENDOR 1) endif() -set(CMAKE_COLOR_MAKEFILE ON) - -set(CMAKE_POSITION_INDEPENDENT_CODE ON) +option(CMAKE_COLOR_MAKEFILE "colorful CMake makefile" ON) +option(CMAKE_VERBOSE_MAKEFILE "verbose CMake makefile" ON) +option(CMAKE_POSITION_INDEPENDENT_CODE "build with position independent code (-fPIC or -fPIE)" ON) # Include our extra modules set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/) @@ -85,7 +85,7 @@ if ($ENV{BUILD_NUMBER}) endif() set(WITH_LIBRARY_VERSIONING "ON") -set(RAW_VERSION_STRING "2.10.0") +set(RAW_VERSION_STRING "2.11.2") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) @@ -225,7 +225,7 @@ endif() if(MSVC) include(MSVCRuntime) if(NOT DEFINED MSVC_RUNTIME) - set(MSVC_RUNTIME "dynamic") + set(MSVC_RUNTIME "dynamic" CACHE STRING "MSVC runtime type [dynamic|static]") endif() if(MSVC_RUNTIME STREQUAL "static") if(BUILD_SHARED_LIBS) diff --git a/ChangeLog b/ChangeLog index 17707a3..9405152 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,42 @@ +# 2023-09-20 Version 2.11.2 + +Notworthy changes: +* Backported #9378: backported wArrayList (optional) copy on insert +* Backported #9360: backported certificate algorithm detection + +For a complete and detailed change log since the last release run: +git log 2.11.2..2.11.1 + +# 2023-09-04 Version 2.11.1 + +Notworthy changes: +* Backported #9356: Fix issues with order updates + +For a complete and detailed change log since the last release run: +git log 2.11.1..2.11.0 + +# 2023-08-28 Version 2.11.0 + +Noteworthy changes: +* Various input validation fixes +* Added various CMake options #9317 +* LibreSSL build fixes #8709 + +Fixed issues: +* Backported #9233: Big endian support +* Backported #9099: Mouse grabbing support +* Backported #6851: wayland scrolling fix +* Backported #8690: Update h264 to use new FFMPEG API +* Backported #7306: early bail from update_read_window_state_order breaks protocol +* Backported #8903: rdpecam/server: Remove wrong assertion +* Backported #8994: bounds checks for gdi/gfx rectangles +* Backported #9023: enforce rdpdr client side state checks +* Backported #6331: deactivate mouse grabbing by default +* Cherry-pick out of #9172: channels/cliprdr: Fix writing incorrect PDU type for unlock PDUs + # 2023-02-16 Version 2.10.0 -Notewhorth changes: +Noteworthy changes: * Fix android build scripts, use CMake from SDK * Fix connection negotiation with mstsc/msrdc #8426 * [ntlm]: use rfc5929 binding hash algorithm #8430 @@ -23,7 +59,7 @@ Fixed issues: # 2022-11-16 Version 2.9.0 -Notewhorth changes: +Noteworthy changes: * Backported #8252: Support sending server redirection PDU * Backported #8406: Ensure X11 client cursor is never smaller 1x1 * Backported #8403: Fixed multiple client side input validation issues @@ -49,7 +85,7 @@ git log 2.8.1..2.9.0 # 2022-10-12 Version 2.8.1 -Notewhorth changes: +Noteworthy changes: * Fixed CVE-2022-39282 * Fixed CVE-2022-39283 * Added missing commit for backported #8041: Remove ALAW/ULAW codecs from linux backends (unreliable) diff --git a/channels/cliprdr/cliprdr_common.c b/channels/cliprdr/cliprdr_common.c index 69157ad..8472fde 100644 --- a/channels/cliprdr/cliprdr_common.c +++ b/channels/cliprdr/cliprdr_common.c @@ -138,7 +138,7 @@ cliprdr_packet_unlock_clipdata_new(const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockCl if (!unlockClipboardData) return NULL; - s = cliprdr_packet_new(CB_LOCK_CLIPDATA, 0, 4); + s = cliprdr_packet_new(CB_UNLOCK_CLIPDATA, 0, 4); if (!s) return NULL; diff --git a/channels/rdpdr/client/devman.c b/channels/rdpdr/client/devman.c index af3cdd6..841e928 100644 --- a/channels/rdpdr/client/devman.c +++ b/channels/rdpdr/client/devman.c @@ -41,6 +41,8 @@ #include "devman.h" +#define TAG CHANNELS_TAG("rdpdr.client") + static void devman_device_free(void* obj) { DEVICE* device = (DEVICE*)obj; @@ -62,7 +64,7 @@ DEVMAN* devman_new(rdpdrPlugin* rdpdr) if (!devman) { - WLog_INFO(TAG, "calloc failed!"); + WLog_Print(rdpdr->log, WLOG_INFO, "calloc failed!"); return NULL; } @@ -72,7 +74,7 @@ DEVMAN* devman_new(rdpdrPlugin* rdpdr) if (!devman->devices) { - WLog_INFO(TAG, "ListDictionary_New failed!"); + WLog_Print(rdpdr->log, WLOG_INFO, "ListDictionary_New failed!"); free(devman); return NULL; } diff --git a/channels/rdpdr/client/irp.c b/channels/rdpdr/client/irp.c index b818b67..b127810 100644 --- a/channels/rdpdr/client/irp.c +++ b/channels/rdpdr/client/irp.c @@ -76,13 +76,13 @@ static UINT irp_complete(IRP* irp) return irp_free(irp); } -IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error) +IRP* irp_new(DEVMAN* devman, wStream* s, wLog* log, UINT* error) { IRP* irp; DEVICE* device; UINT32 DeviceId; - if (Stream_GetRemainingLength(s) < 20) + if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20)) { if (error) *error = ERROR_INVALID_DATA; @@ -94,7 +94,7 @@ IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error) if (!device) { - WLog_WARN(TAG, "devman_get_device_by_id failed!"); + WLog_Print(log, WLOG_WARN, "devman_get_device_by_id failed!"); if (error) *error = CHANNEL_RC_OK; @@ -105,7 +105,7 @@ IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error) if (!irp) { - WLog_ERR(TAG, "_aligned_malloc failed!"); + WLog_Print(log, WLOG_ERROR, "_aligned_malloc failed!"); if (error) *error = CHANNEL_RC_NO_MEMORY; return NULL; @@ -125,7 +125,7 @@ IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error) irp->output = Stream_New(NULL, 256); if (!irp->output) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(log, WLOG_ERROR, "Stream_New failed!"); _aligned_free(irp); if (error) *error = CHANNEL_RC_NO_MEMORY; diff --git a/channels/rdpdr/client/irp.h b/channels/rdpdr/client/irp.h index 17d75ac..46a67be 100644 --- a/channels/rdpdr/client/irp.h +++ b/channels/rdpdr/client/irp.h @@ -21,8 +21,9 @@ #ifndef FREERDP_CHANNEL_RDPDR_CLIENT_IRP_H #define FREERDP_CHANNEL_RDPDR_CLIENT_IRP_H +#include #include "rdpdr_main.h" -IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error); +IRP* irp_new(DEVMAN* devman, wStream* s, wLog* log, UINT* error); #endif /* FREERDP_CHANNEL_RDPDR_CLIENT_IRP_H */ diff --git a/channels/rdpdr/client/rdpdr_capabilities.c b/channels/rdpdr/client/rdpdr_capabilities.c index 97c876b..7669766 100644 --- a/channels/rdpdr/client/rdpdr_capabilities.c +++ b/channels/rdpdr/client/rdpdr_capabilities.c @@ -69,7 +69,7 @@ static UINT rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s) UINT16 capabilityLength; WINPR_UNUSED(rdpdr); - if (Stream_GetRemainingLength(s) < 2) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 2)) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityLength); @@ -77,7 +77,7 @@ static UINT rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s) if (capabilityLength < 4) return ERROR_INVALID_DATA; - if (Stream_GetRemainingLength(s) < capabilityLength - 4U) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, capabilityLength - 4U)) return ERROR_INVALID_DATA; Stream_Seek(s, capabilityLength - 4U); @@ -97,7 +97,7 @@ static UINT rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s) UINT16 capabilityLength; WINPR_UNUSED(rdpdr); - if (Stream_GetRemainingLength(s) < 2) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 2)) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityLength); @@ -105,7 +105,7 @@ static UINT rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s) if (capabilityLength < 4) return ERROR_INVALID_DATA; - if (Stream_GetRemainingLength(s) < capabilityLength - 4U) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, capabilityLength - 4U)) return ERROR_INVALID_DATA; Stream_Seek(s, capabilityLength - 4U); @@ -125,7 +125,7 @@ static UINT rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s) UINT16 capabilityLength; WINPR_UNUSED(rdpdr); - if (Stream_GetRemainingLength(s) < 2) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 2)) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityLength); @@ -133,7 +133,7 @@ static UINT rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s) if (capabilityLength < 4U) return ERROR_INVALID_DATA; - if (Stream_GetRemainingLength(s) < capabilityLength - 4U) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, capabilityLength - 4U)) return ERROR_INVALID_DATA; Stream_Seek(s, capabilityLength - 4U); @@ -153,7 +153,7 @@ static UINT rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s) UINT16 capabilityLength; WINPR_UNUSED(rdpdr); - if (Stream_GetRemainingLength(s) < 2) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 2)) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityLength); @@ -161,7 +161,7 @@ static UINT rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s) if (capabilityLength < 4) return ERROR_INVALID_DATA; - if (Stream_GetRemainingLength(s) < capabilityLength - 4U) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, capabilityLength - 4U)) return ERROR_INVALID_DATA; Stream_Seek(s, capabilityLength - 4U); @@ -181,7 +181,7 @@ static UINT rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) UINT16 capabilityLength; WINPR_UNUSED(rdpdr); - if (Stream_GetRemainingLength(s) < 2) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 2)) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityLength); @@ -189,7 +189,7 @@ static UINT rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) if (capabilityLength < 4) return ERROR_INVALID_DATA; - if (Stream_GetRemainingLength(s) < capabilityLength - 4U) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, capabilityLength - 4U)) return ERROR_INVALID_DATA; Stream_Seek(s, capabilityLength - 4U); @@ -206,7 +206,10 @@ UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s) if (!rdpdr || !s) return CHANNEL_RC_NULL_DATA; - if (Stream_GetRemainingLength(s) < 4) + WINPR_ASSERT(rdpdr->state == RDPDR_CHANNEL_STATE_SERVER_CAPS); + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_CLIENT_CAPS); + + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4)) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, numCapabilities); @@ -214,7 +217,7 @@ UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s) for (i = 0; i < numCapabilities; i++) { - if (Stream_GetRemainingLength(s) < sizeof(UINT16)) + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, sizeof(UINT16))) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityType); @@ -264,7 +267,7 @@ UINT rdpdr_send_capability_response(rdpdrPlugin* rdpdr) if (!s) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 681ebce..adaaf1d 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -79,12 +79,50 @@ struct _DEVICE_DRIVE_EXT BOOL automount; }; +static const char* rdpdr_state_str(enum RDPDR_CHANNEL_STATE state) +{ + switch (state) + { + case RDPDR_CHANNEL_STATE_INITIAL: + return "RDPDR_CHANNEL_STATE_INITIAL"; + case RDPDR_CHANNEL_STATE_ANNOUNCE: + return "RDPDR_CHANNEL_STATE_ANNOUNCE"; + case RDPDR_CHANNEL_STATE_ANNOUNCE_REPLY: + return "RDPDR_CHANNEL_STATE_ANNOUNCE_REPLY"; + case RDPDR_CHANNEL_STATE_NAME_REQUEST: + return "RDPDR_CHANNEL_STATE_NAME_REQUEST"; + case RDPDR_CHANNEL_STATE_SERVER_CAPS: + return "RDPDR_CHANNEL_STATE_SERVER_CAPS"; + case RDPDR_CHANNEL_STATE_CLIENT_CAPS: + return "RDPDR_CHANNEL_STATE_CLIENT_CAPS"; + case RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM: + return "RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM"; + case RDPDR_CHANNEL_STATE_READY: + return "RDPDR_CHANNEL_STATE_READY"; + case RDPDR_CHANNEL_STATE_USER_LOGGEDON: + return "RDPDR_CHANNEL_STATE_USER_LOGGEDON"; + default: + return "RDPDR_CHANNEL_STATE_UNKNOWN"; + } +} + +BOOL rdpdr_state_advance(rdpdrPlugin* rdpdr, enum RDPDR_CHANNEL_STATE next) +{ + WINPR_ASSERT(rdpdr); + + if (next != rdpdr->state) + WLog_Print(rdpdr->log, WLOG_DEBUG, "[RDPDR] transition from %s to %s", + rdpdr_state_str(rdpdr->state), rdpdr_state_str(next)); + rdpdr->state = next; + return TRUE; +} + /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL userLoggedOn); +static UINT rdpdr_try_send_device_list_announce_request(rdpdrPlugin* rdpdr); /** * Function description @@ -99,7 +137,7 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou if (!s) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -212,7 +250,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) devman_load_device_service(rdpdr->devman, (const RDPDR_DEVICE*)&drive, rdpdr->rdpcontext); - rdpdr_send_device_list_announce_request(rdpdr, TRUE); + rdpdr_try_send_device_list_announce_request(rdpdr); } } @@ -261,8 +299,8 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) rdpdr, 1, ids))) { // dont end on error, just report ? - WLog_ERR( - TAG, + WLog_Print( + rdpdr->log, WLOG_ERROR, "rdpdr_send_device_list_remove_request failed " "with error %" PRIu32 "!", error); @@ -358,7 +396,7 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) if (rdpdr->hotplug_wnd && !PostMessage(rdpdr->hotplug_wnd, WM_QUIT, 0, 0)) { error = GetLastError(); - WLog_ERR(TAG, "PostMessage failed with error %" PRIu32 "", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "PostMessage failed with error %" PRIu32 "", error); } return error; @@ -475,9 +513,9 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids))) { - WLog_ERR(TAG, - "rdpdr_send_device_list_remove_request failed with error %" PRIu32 "!", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_send_device_list_remove_request failed with error %" PRIu32 "!", + error); goto cleanup; } } @@ -506,7 +544,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)&drive, rdpdr->rdpcontext))) { - WLog_ERR(TAG, "devman_load_device_service failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "devman_load_device_service failed!"); error = CHANNEL_RC_NO_MEMORY; goto cleanup; } @@ -540,10 +578,11 @@ static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef, { if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!", + error); } else - rdpdr_send_device_list_announce_request(rdpdr, TRUE); + rdpdr_try_send_device_list_announce_request(rdpdr); return; } @@ -556,7 +595,7 @@ void first_hotplug(rdpdrPlugin* rdpdr) if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!", error); } } @@ -661,14 +700,14 @@ static void handle_mountpoint(hotplug_dev* dev_array, size_t* size, const char* #ifdef __sun #include -static UINT handle_platform_mounts_sun(hotplug_dev* dev_array, size_t* size) +static UINT handle_platform_mounts_sun(wLog* log, 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!"); + WLog_Print(log, WLOG_ERROR, "fopen failed!"); return ERROR_OPEN_FAILED; } while (getmntent(f, &ent) == 0) @@ -682,7 +721,7 @@ static UINT handle_platform_mounts_sun(hotplug_dev* dev_array, size_t* size) #if defined(__FreeBSD__) || defined(__OpenBSD__) #include -static UINT handle_platform_mounts_bsd(hotplug_dev* dev_array, size_t* size) +static UINT handle_platform_mounts_bsd(wLog* log, hotplug_dev* dev_array, size_t* size) { int mntsize; size_t idx; @@ -692,7 +731,7 @@ static UINT handle_platform_mounts_bsd(hotplug_dev* dev_array, size_t* size) if (!mntsize) { /* TODO: handle 'errno' */ - WLog_ERR(TAG, "getmntinfo failed!"); + WLog_Print(log, WLOG_ERROR, "getmntinfo failed!"); return ERROR_OPEN_FAILED; } for (idx = 0; idx < (size_t)mntsize; idx++) @@ -706,14 +745,14 @@ static UINT handle_platform_mounts_bsd(hotplug_dev* dev_array, size_t* size) #if defined(__LINUX__) || defined(__linux__) #include -static UINT handle_platform_mounts_linux(hotplug_dev* dev_array, size_t* size) +static UINT handle_platform_mounts_linux(wLog* log, 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!"); + WLog_Print(log, WLOG_ERROR, "fopen failed!"); return ERROR_OPEN_FAILED; } while ((ent = getmntent(f)) != NULL) @@ -725,14 +764,14 @@ static UINT handle_platform_mounts_linux(hotplug_dev* dev_array, size_t* size) } #endif -static UINT handle_platform_mounts(hotplug_dev* dev_array, size_t* size) +static UINT handle_platform_mounts(wLog* log, hotplug_dev* dev_array, size_t* size) { #ifdef __sun - return handle_platform_mounts_sun(dev_array, size); + return handle_platform_mounts_sun(log, dev_array, size); #elif defined(__FreeBSD__) || defined(__OpenBSD__) - return handle_platform_mounts_bsd(dev_array, size); + return handle_platform_mounts_bsd(log, dev_array, size); #elif defined(__LINUX__) || defined(__linux__) - return handle_platform_mounts_linux(dev_array, size); + return handle_platform_mounts_linux(log, dev_array, size); #endif return ERROR_CALL_NOT_IMPLEMENTED; } @@ -790,7 +829,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) UINT32 ids[1]; UINT error = ERROR_SUCCESS; - error = handle_platform_mounts(dev_array, &size); + error = handle_platform_mounts(rdpdr->log, dev_array, &size); /* delete removed devices */ count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys); @@ -834,9 +873,9 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids))) { - WLog_ERR(TAG, - "rdpdr_send_device_list_remove_request failed with error %" PRIu32 "!", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_send_device_list_remove_request failed with error %" PRIu32 "!", + error); goto cleanup; } } @@ -858,7 +897,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) if (!drive.Name) { - WLog_ERR(TAG, "_strdup failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "_strdup failed!"); error = CHANNEL_RC_NO_MEMORY; goto cleanup; } @@ -866,7 +905,7 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) if ((error = devman_load_device_service(rdpdr->devman, (const RDPDR_DEVICE*)&drive, rdpdr->rdpcontext))) { - WLog_ERR(TAG, "devman_load_device_service failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "devman_load_device_service failed!"); goto cleanup; } } @@ -887,7 +926,7 @@ static void first_hotplug(rdpdrPlugin* rdpdr) if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!", error); } } @@ -905,7 +944,7 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) if (mfd < 0) { - WLog_ERR(TAG, "ERROR: Unable to open /proc/mounts."); + WLog_Print(rdpdr->log, WLOG_ERROR, "ERROR: Unable to open /proc/mounts."); error = ERROR_INTERNAL_ERROR; goto out; } @@ -922,7 +961,8 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!", + error); goto out; } @@ -934,11 +974,12 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) /* file /proc/mounts changed, handle this */ if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "handle_hotplug failed with error %" PRIu32 "!", + error); goto out; } else - rdpdr_send_device_list_announce_request(rdpdr, TRUE); + rdpdr_try_send_device_list_announce_request(rdpdr); } FD_ZERO(&rfds); @@ -978,7 +1019,8 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) if (WaitForSingleObject(rdpdr->hotplugThread, INFINITE) == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!", + error); return error; } @@ -1007,7 +1049,7 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) if (!rdpdr->devman) { - WLog_ERR(TAG, "devman_new failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "devman_new failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1036,7 +1078,7 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) if (!(rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { - WLog_ERR(TAG, "CreateEvent failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "CreateEvent failed!"); return ERROR_INTERNAL_ERROR; } @@ -1045,7 +1087,7 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) if (!(rdpdr->hotplugThread = CreateThread(NULL, 0, drive_hotplug_thread_func, rdpdr, 0, NULL))) { - WLog_ERR(TAG, "CreateThread failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "CreateThread failed!"); #ifndef _WIN32 CloseHandle(rdpdr->stopEvent); rdpdr->stopEvent = NULL; @@ -1059,7 +1101,8 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) if ((error = devman_load_device_service(rdpdr->devman, device, rdpdr->rdpcontext))) { - WLog_ERR(TAG, "devman_load_device_service failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "devman_load_device_service failed with error %" PRIu32 "!", error); return error; } } @@ -1087,11 +1130,16 @@ static UINT rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, wStream* s static UINT rdpdr_send_client_announce_reply(rdpdrPlugin* rdpdr) { wStream* s; + + WINPR_ASSERT(rdpdr); + WINPR_ASSERT(rdpdr->state == RDPDR_CHANNEL_STATE_ANNOUNCE); + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_ANNOUNCE_REPLY); + s = Stream_New(NULL, 12); if (!s) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1114,6 +1162,10 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr) WCHAR* computerNameW = NULL; size_t computerNameLenW; + WINPR_ASSERT(rdpdr); + WINPR_ASSERT(rdpdr->state == RDPDR_CHANNEL_STATE_ANNOUNCE_REPLY); + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_NAME_REQUEST); + if (!rdpdr->computerName[0]) { DWORD size = sizeof(rdpdr->computerName) - 1; @@ -1126,7 +1178,7 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr) if (!s) { free(computerNameW); - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1147,7 +1199,10 @@ static UINT rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, wStream* s UINT16 versionMinor; UINT32 clientID; - if (Stream_GetRemainingLength(s) < 8) + WINPR_ASSERT(rdpdr); + WINPR_ASSERT(s); + + if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 8)) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, versionMajor); @@ -1184,11 +1239,23 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use DEVICE* device; int keyCount; ULONG_PTR* pKeys = NULL; + + if (userLoggedOn) + { + WINPR_ASSERT(rdpdr->state >= RDPDR_CHANNEL_STATE_READY); + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_USER_LOGGEDON); + } + else + { + WINPR_ASSERT(rdpdr->state >= RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM); + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_READY); + } + s = Stream_New(NULL, 256); if (!s) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1220,7 +1287,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use { free(pKeys); Stream_Free(s, TRUE); - WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); return ERROR_INVALID_DATA; } @@ -1244,8 +1311,9 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use Stream_Write(s, Stream_Buffer(device->data), data_len); count++; - WLog_INFO(TAG, "registered device #%" PRIu32 ": %s (type=%" PRIu32 " id=%" PRIu32 ")", - count, device->name, device->type, device->id); + WLog_Print(rdpdr->log, WLOG_INFO, + "registered device #%" PRIu32 ": %s (type=%" PRIu32 " id=%" PRIu32 ")", + count, device->name, device->type, device->id); } } @@ -1258,6 +1326,19 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use return rdpdr_send(rdpdr, s); } +UINT rdpdr_try_send_device_list_announce_request(rdpdrPlugin* rdpdr) +{ + WINPR_ASSERT(rdpdr); + if (rdpdr->state != RDPDR_CHANNEL_STATE_USER_LOGGEDON) + { + WLog_Print(rdpdr->log, WLOG_DEBUG, + "hotplug event received, but channel [RDPDR] is not ready (state %s), ignoring.", + rdpdr_state_str(rdpdr->state)); + return CHANNEL_RC_OK; + } + return rdpdr_send_device_list_announce_request(rdpdr, TRUE); +} + static UINT dummy_irp_response(rdpdrPlugin* rdpdr, wStream* s) { @@ -1268,7 +1349,7 @@ static UINT dummy_irp_response(rdpdrPlugin* rdpdr, wStream* s) wStream* output = Stream_New(NULL, 256); // RDPDR_DEVICE_IO_RESPONSE_LENGTH if (!output) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1301,11 +1382,11 @@ static UINT rdpdr_process_irp(rdpdrPlugin* rdpdr, wStream* s) { IRP* irp; UINT error = CHANNEL_RC_OK; - irp = irp_new(rdpdr->devman, s, &error); + irp = irp_new(rdpdr->devman, s, rdpdr->log, &error); if (!irp) { - WLog_ERR(TAG, "irp_new failed with %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "irp_new failed with %" PRIu32 "!", error); if (error == CHANNEL_RC_OK) { @@ -1317,8 +1398,11 @@ static UINT rdpdr_process_irp(rdpdrPlugin* rdpdr, wStream* s) IFCALLRET(irp->device->IRPRequest, error, irp->device, irp); - if (error) - WLog_ERR(TAG, "device->IRPRequest failed with error %" PRIu32 "", error); + if (error != CHANNEL_RC_OK) + { + WLog_Print(rdpdr->log, WLOG_ERROR, "device->IRPRequest failed with error %" PRIu32 "", + error); + } return error; } @@ -1370,7 +1454,7 @@ static UINT rdpdr_process_init(rdpdrPlugin* rdpdr) if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, "Init failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Init failed!"); free(pKeys); return error; } @@ -1380,6 +1464,58 @@ static UINT rdpdr_process_init(rdpdrPlugin* rdpdr) return CHANNEL_RC_OK; } +static BOOL rdpdr_state_check(rdpdrPlugin* rdpdr, UINT16 packetid, + enum RDPDR_CHANNEL_STATE expected, enum RDPDR_CHANNEL_STATE next) +{ + WINPR_ASSERT(rdpdr); + + const char* strstate = rdpdr_state_str(rdpdr->state); + if (rdpdr->state != expected) + { + WLog_Print(rdpdr->log, WLOG_ERROR, + "channel [RDPDR] received %" PRIu16 + ", expected state %s but have state %s, aborting.", + packetid, rdpdr_state_str(expected), strstate); + + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_INITIAL); + return FALSE; + } + return rdpdr_state_advance(rdpdr, next); +} + +static BOOL rdpdr_check_channel_state(rdpdrPlugin* rdpdr, UINT16 packetid) +{ + WINPR_ASSERT(rdpdr); + + switch (packetid) + { + case PAKID_CORE_SERVER_ANNOUNCE: + /* windows servers sometimes send this message. + * it seems related to session login (e.g. first initialization for RDP/TLS style login, + * then reinitialize the channel after login successful + */ + rdpdr_state_advance(rdpdr, RDPDR_CHANNEL_STATE_INITIAL); + return rdpdr_state_check(rdpdr, packetid, RDPDR_CHANNEL_STATE_INITIAL, + RDPDR_CHANNEL_STATE_ANNOUNCE); + case PAKID_CORE_SERVER_CAPABILITY: + return rdpdr_state_check(rdpdr, packetid, RDPDR_CHANNEL_STATE_NAME_REQUEST, + RDPDR_CHANNEL_STATE_SERVER_CAPS); + case PAKID_CORE_CLIENTID_CONFIRM: + return rdpdr_state_check(rdpdr, packetid, RDPDR_CHANNEL_STATE_CLIENT_CAPS, + RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM); + case PAKID_CORE_USER_LOGGEDON: + return rdpdr_state_check(rdpdr, packetid, RDPDR_CHANNEL_STATE_READY, + RDPDR_CHANNEL_STATE_USER_LOGGEDON); + default: + { + enum RDPDR_CHANNEL_STATE state = RDPDR_CHANNEL_STATE_READY; + if (rdpdr->state == RDPDR_CHANNEL_STATE_USER_LOGGEDON) + state = RDPDR_CHANNEL_STATE_USER_LOGGEDON; + return rdpdr_state_check(rdpdr, packetid, state, state); + } + } +} + /** * Function description * @@ -1403,6 +1539,9 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) if (component == RDPDR_CTYP_CORE) { + if (!rdpdr_check_channel_state(rdpdr, packetId)) + return CHANNEL_RC_OK; + switch (packetId) { case PAKID_CORE_SERVER_ANNOUNCE: @@ -1411,19 +1550,20 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) } else if ((error = rdpdr_send_client_announce_reply(rdpdr))) { - WLog_ERR(TAG, - "rdpdr_send_client_announce_reply failed with error %" PRIu32 "", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_send_client_announce_reply failed with error %" PRIu32 "", + error); } else if ((error = rdpdr_send_client_name_request(rdpdr))) { - WLog_ERR(TAG, - "rdpdr_send_client_name_request failed with error %" PRIu32 "", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_send_client_name_request failed with error %" PRIu32 "", + error); } else if ((error = rdpdr_process_init(rdpdr))) { - WLog_ERR(TAG, "rdpdr_process_init failed with error %" PRIu32 "", error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_process_init failed with error %" PRIu32 "", error); } break; @@ -1434,9 +1574,9 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) } else if ((error = rdpdr_send_capability_response(rdpdr))) { - WLog_ERR(TAG, - "rdpdr_send_capability_response failed with error %" PRIu32 "", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_send_capability_response failed with error %" PRIu32 "", + error); } break; @@ -1447,8 +1587,8 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) } else if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE))) { - WLog_ERR( - TAG, + WLog_Print( + rdpdr->log, WLOG_ERROR, "rdpdr_send_device_list_announce_request failed with error %" PRIu32 "", error); } @@ -1458,8 +1598,8 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) case PAKID_CORE_USER_LOGGEDON: if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE))) { - WLog_ERR( - TAG, + WLog_Print( + rdpdr->log, WLOG_ERROR, "rdpdr_send_device_list_announce_request failed with error %" PRIu32 "", error); } @@ -1481,7 +1621,8 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) case PAKID_CORE_DEVICE_IOREQUEST: if ((error = rdpdr_process_irp(rdpdr, s))) { - WLog_ERR(TAG, "rdpdr_process_irp failed with error %" PRIu32 "", error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_process_irp failed with error %" PRIu32 "", error); return error; } else @@ -1490,7 +1631,8 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) break; default: - WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04" PRIX16 "", packetId); + WLog_Print(rdpdr->log, WLOG_ERROR, + "RDPDR_CTYP_CORE unknown PacketId: 0x%04" PRIX16 "", packetId); error = ERROR_INVALID_DATA; break; } @@ -1501,9 +1643,10 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, - "Unknown message: Component: 0x%04" PRIX16 " PacketId: 0x%04" PRIX16 "", - component, packetId); + WLog_Print(rdpdr->log, WLOG_ERROR, + "Unknown message: Component: [0x%04" PRIX16 "] PacketId: [0x%04" PRIX16 + "]", + component, packetId); } } } @@ -1543,8 +1686,8 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s) if (status != CHANNEL_RC_OK) { Stream_Free(s, TRUE); - WLog_ERR(TAG, "pVirtualChannelWriteEx failed with %s [%08" PRIX32 "]", - WTSErrorToString(status), status); + WLog_Print(rdpdr->log, WLOG_ERROR, "pVirtualChannelWriteEx failed with %s [%08" PRIX32 "]", + WTSErrorToString(status), status); } return status; @@ -1581,7 +1724,7 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, void* if (!rdpdr->data_in) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } } @@ -1590,7 +1733,7 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, void* if (!Stream_EnsureRemainingCapacity(data_in, dataLength)) { - WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); return ERROR_INVALID_DATA; } @@ -1600,7 +1743,8 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, void* { if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { - WLog_ERR(TAG, "rdpdr_virtual_channel_event_data_received: read error"); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_virtual_channel_event_data_received: read error"); return ERROR_INTERNAL_ERROR; } @@ -1610,7 +1754,7 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, void* if (!MessageQueue_Post(rdpdr->queue, NULL, 0, (void*)data_in, NULL)) { - WLog_ERR(TAG, "MessageQueue_Post failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; } } @@ -1631,14 +1775,15 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event_ex(LPVOID lpUserParam, DW case CHANNEL_EVENT_DATA_RECEIVED: if (!rdpdr || !pData || (rdpdr->OpenHandle != openHandle)) { - WLog_ERR(TAG, "error no match"); + WLog_Print(rdpdr->log, WLOG_ERROR, "error no match"); return; } if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, totalLength, dataFlags))) - WLog_ERR(TAG, - "rdpdr_virtual_channel_event_data_received failed with error %" PRIu32 "!", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_virtual_channel_event_data_received failed with error %" PRIu32 + "!", + error); break; @@ -1676,7 +1821,8 @@ static DWORD WINAPI rdpdr_virtual_channel_client_thread(LPVOID arg) if ((error = rdpdr_process_connect(rdpdr))) { - WLog_ERR(TAG, "rdpdr_process_connect failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "rdpdr_process_connect failed with error %" PRIu32 "!", + error); if (rdpdr->rdpcontext) setChannelError(rdpdr->rdpcontext, error, @@ -1702,7 +1848,8 @@ static DWORD WINAPI rdpdr_virtual_channel_client_thread(LPVOID arg) if ((error = rdpdr_process_receive(rdpdr, data))) { - WLog_ERR(TAG, "rdpdr_process_receive failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_process_receive failed with error %" PRIu32 "!", error); if (rdpdr->rdpcontext) setChannelError(rdpdr->rdpcontext, error, @@ -1740,8 +1887,8 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pDa if (status != CHANNEL_RC_OK) { - WLog_ERR(TAG, "pVirtualChannelOpenEx failed with %s [%08" PRIX32 "]", - WTSErrorToString(status), status); + WLog_Print(rdpdr->log, WLOG_ERROR, "pVirtualChannelOpenEx failed with %s [%08" PRIX32 "]", + WTSErrorToString(status), status); return status; } @@ -1749,7 +1896,7 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pDa if (!rdpdr->queue) { - WLog_ERR(TAG, "MessageQueue_New failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "MessageQueue_New failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -1758,7 +1905,7 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pDa if (!(rdpdr->thread = CreateThread(NULL, 0, rdpdr_virtual_channel_client_thread, (void*)rdpdr, 0, NULL))) { - WLog_ERR(TAG, "CreateThread failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "CreateThread failed!"); return ERROR_INTERNAL_ERROR; } @@ -1781,7 +1928,8 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) (WaitForSingleObject(rdpdr->thread, INFINITE) == WAIT_FAILED)) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!", + error); return error; } @@ -1792,7 +1940,8 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) if ((error = drive_hotplug_thread_terminate(rdpdr))) { - WLog_ERR(TAG, "drive_hotplug_thread_terminate failed with error %" PRIu32 "!", error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "drive_hotplug_thread_terminate failed with error %" PRIu32 "!", error); return error; } @@ -1800,8 +1949,8 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) if (CHANNEL_RC_OK != error) { - WLog_ERR(TAG, "pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", - WTSErrorToString(error), error); + WLog_Print(rdpdr->log, WLOG_ERROR, "pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", + WTSErrorToString(error), error); } rdpdr->OpenHandle = 0; @@ -1835,7 +1984,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LP if (!rdpdr || (rdpdr->InitHandle != pInitHandle)) { - WLog_ERR(TAG, "error no match"); + WLog_Print(rdpdr->log, WLOG_ERROR, "error no match"); return; } @@ -1846,17 +1995,18 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LP case CHANNEL_EVENT_CONNECTED: if ((error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength))) - WLog_ERR(TAG, - "rdpdr_virtual_channel_event_connected failed with error %" PRIu32 "!", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_virtual_channel_event_connected failed with error %" PRIu32 "!", + error); break; case CHANNEL_EVENT_DISCONNECTED: if ((error = rdpdr_virtual_channel_event_disconnected(rdpdr))) - WLog_ERR(TAG, - "rdpdr_virtual_channel_event_disconnected failed with error %" PRIu32 "!", - error); + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_virtual_channel_event_disconnected failed with error %" PRIu32 + "!", + error); break; @@ -1867,7 +2017,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LP case CHANNEL_EVENT_ATTACHED: case CHANNEL_EVENT_DETACHED: default: - WLog_ERR(TAG, "unknown event %" PRIu32 "!", event); + WLog_Print(rdpdr->log, WLOG_ERROR, "unknown event %" PRIu32 "!", event); break; } @@ -1877,6 +2027,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LP } /* rdpdr is always built-in */ +#define TAG CHANNELS_TAG("rdpdr.client") #define VirtualChannelEntryEx rdpdr_VirtualChannelEntryEx BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID pInitHandle) @@ -1888,9 +2039,11 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p if (!rdpdr) { - WLog_ERR(TAG, "calloc failed!"); + WLog_Print(rdpdr->log, WLOG_ERROR, "calloc failed!"); return FALSE; } + rdpdr->log = WLog_Get(TAG); + WINPR_ASSERT(rdpdr->log); rdpdr->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP; @@ -1912,8 +2065,8 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p if (CHANNEL_RC_OK != rc) { - WLog_ERR(TAG, "pVirtualChannelInitEx failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), - rc); + WLog_Print(rdpdr->log, WLOG_ERROR, "pVirtualChannelInitEx failed with %s [%08" PRIX32 "]", + WTSErrorToString(rc), rc); free(rdpdr); return FALSE; } diff --git a/channels/rdpdr/client/rdpdr_main.h b/channels/rdpdr/client/rdpdr_main.h index 4c372da..37ffb5f 100644 --- a/channels/rdpdr/client/rdpdr_main.h +++ b/channels/rdpdr/client/rdpdr_main.h @@ -42,15 +42,33 @@ #include #endif -#define TAG CHANNELS_TAG("rdpdr.client") +#if !defined(Stream_CheckAndLogRequiredLengthWLog) +#define Stream_CheckAndLogRequiredLengthWLog(log, s, len) \ + Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, "%s(%s:%d)", __FUNCTION__, \ + __FILE__, __LINE__) +#endif typedef struct rdpdr_plugin rdpdrPlugin; +enum RDPDR_CHANNEL_STATE +{ + RDPDR_CHANNEL_STATE_INITIAL = 0, + RDPDR_CHANNEL_STATE_ANNOUNCE, + RDPDR_CHANNEL_STATE_ANNOUNCE_REPLY, + RDPDR_CHANNEL_STATE_NAME_REQUEST, + RDPDR_CHANNEL_STATE_SERVER_CAPS, + RDPDR_CHANNEL_STATE_CLIENT_CAPS, + RDPDR_CHANNEL_STATE_CLIENTID_CONFIRM, + RDPDR_CHANNEL_STATE_READY, + RDPDR_CHANNEL_STATE_USER_LOGGEDON +}; + struct rdpdr_plugin { CHANNEL_DEF channelDef; CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints; + enum RDPDR_CHANNEL_STATE state; HANDLE thread; wStream* data_in; void* InitHandle; @@ -78,8 +96,10 @@ struct rdpdr_plugin HANDLE stopEvent; #endif rdpContext* rdpcontext; + wLog* log; }; +BOOL rdpdr_state_advance(rdpdrPlugin* rdpdr, enum RDPDR_CHANNEL_STATE next); UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s); #endif /* FREERDP_CHANNEL_RDPDR_CLIENT_MAIN_H */ diff --git a/channels/rdpecam/server/camera_device_main.c b/channels/rdpecam/server/camera_device_main.c index 00bea94..941a288 100644 --- a/channels/rdpecam/server/camera_device_main.c +++ b/channels/rdpecam/server/camera_device_main.c @@ -686,8 +686,6 @@ static wStream* device_server_packet_new(size_t size, BYTE version, BYTE message { wStream* s; - WINPR_ASSERT(size > 0); - /* Allocate what we need plus header bytes */ s = Stream_New(NULL, size + CAM_HEADER_SIZE); if (!s) diff --git a/channels/rdpsnd/server/rdpsnd_main.c b/channels/rdpsnd/server/rdpsnd_main.c index 363fac7..a26c3cf 100644 --- a/channels/rdpsnd/server/rdpsnd_main.c +++ b/channels/rdpsnd/server/rdpsnd_main.c @@ -523,7 +523,7 @@ static UINT rdpsnd_server_send_wave_pdu(RdpsndServerContext* context, UINT16 wTi Stream_Seek(s, 3); /* bPad */ start = Stream_GetPosition(s); src = context->priv->out_buffer; - length = context->priv->out_pending_frames * context->priv->src_bytes_per_frame * 1ULL; + length = 1ull * context->priv->out_pending_frames * context->priv->src_bytes_per_frame; if (!freerdp_dsp_encode(context->priv->dsp_context, context->src_format, src, length, s)) return ERROR_INTERNAL_ERROR; diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c index c14877b..2153374 100644 --- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c @@ -235,8 +235,10 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP } } +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100) if (mdecoder->codec->capabilities & AV_CODEC_CAP_TRUNCATED) mdecoder->codec_context->flags |= AV_CODEC_FLAG_TRUNCATED; +#endif return TRUE; } diff --git a/client/Wayland/wlf_input.c b/client/Wayland/wlf_input.c index 22041ea..735245b 100644 --- a/client/Wayland/wlf_input.c +++ b/client/Wayland/wlf_input.c @@ -134,26 +134,44 @@ BOOL wlf_handle_pointer_buttons(freerdp* instance, const UwacPointerButtonEvent* } BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev) +{ + wlfContext* context; + if (!instance || !instance->context || !ev) + return FALSE; + + context = (wlfContext*)instance->context; + ArrayList_Add(context->events, ev); + return TRUE; +} + +BOOL wlf_handle_pointer_axis_discrete(freerdp* instance, const UwacPointerAxisEvent* ev) +{ + wlfContext* context; + if (!instance || !instance->context || !ev) + return FALSE; + + context = (wlfContext*)instance->context; + ArrayList_Add(context->events, ev); + return TRUE; +} + +static BOOL wlf_handle_wheel(freerdp* instance, uint32_t x, uint32_t y, uint32_t axis, + int32_t value) { rdpInput* input; UINT16 flags = 0; int32_t direction; - uint32_t x, y; - uint32_t i; + uint32_t avalue = abs(value); - if (!instance || !ev || !instance->input) - return FALSE; - - x = ev->x; - y = ev->y; + input = instance->input; if (!wlf_scale_coordinates(instance->context, &x, &y, TRUE)) return FALSE; input = instance->input; - direction = ev->value; - switch (ev->axis) + direction = value; + switch (axis) { case WL_POINTER_AXIS_VERTICAL_SCROLL: flags |= PTR_FLAGS_WHEEL; @@ -176,16 +194,102 @@ BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev) * positive: 0 ... 0xFF -> slow ... fast * negative: 0 ... 0xFF -> fast ... slow */ - for (i = 0; i < abs(direction); i++) + + while (avalue > 0) { - uint32_t cflags = flags | 0x78; + const uint32_t cval = avalue > 0xFF ? 0xFF : avalue; + uint32_t cflags = flags | cval; /* Convert negative values to 9bit twos complement */ if (flags & PTR_FLAGS_WHEEL_NEGATIVE) - cflags = (flags & 0xFF00) | (0x100 - (cflags & 0xFF)); + cflags = (flags & 0xFF00) | (0x100 - cval); if (!freerdp_input_send_mouse_event(input, cflags, (UINT16)x, (UINT16)y)) return FALSE; + + avalue -= cval; + } + return TRUE; +} + +BOOL wlf_handle_pointer_frame(freerdp* instance, const UwacPointerFrameEvent* ev) +{ + BOOL success = TRUE; + BOOL handle = FALSE; + size_t x; + wlfContext* context; + enum wl_pointer_axis_source source; + + if (!instance || !ev || !instance->input || !instance->context) + return FALSE; + + context = (wlfContext*)instance->context; + + for (x = 0; x < ArrayList_Count(context->events); x++) + { + UwacEvent* ev = ArrayList_GetItem(context->events, x); + if (!ev) + continue; + if (ev->type == UWAC_EVENT_POINTER_SOURCE) + { + handle = TRUE; + source = ev->mouse_source.axis_source; + } } + /* We need source events to determine how to interpret the data */ + if (handle) + { + for (x = 0; x < ArrayList_Count(context->events); x++) + { + UwacEvent* ev = ArrayList_GetItem(context->events, x); + if (!ev) + continue; + + switch (source) + { + /* If we have a mouse wheel, just use discrete data */ + case WL_POINTER_AXIS_SOURCE_WHEEL: +#if defined(WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION) + case WL_POINTER_AXIS_SOURCE_WHEEL_TILT: +#endif + if (ev->type == UWAC_EVENT_POINTER_AXIS_DISCRETE) + { + /* Get the number of steps, multiply by default step width of 120 */ + int32_t val = ev->mouse_axis.value * 0x78; + /* No wheel event received, success! */ + if (!wlf_handle_wheel(instance, ev->mouse_axis.x, ev->mouse_axis.y, + ev->mouse_axis.axis, val)) + success = FALSE; + } + break; + /* If we have a touch pad we get actual data, scale */ + case WL_POINTER_AXIS_SOURCE_FINGER: + case WL_POINTER_AXIS_SOURCE_CONTINUOUS: + if (ev->type == UWAC_EVENT_POINTER_AXIS) + { + double dval = wl_fixed_to_double(ev->mouse_axis.value); + int32_t val = dval * 0x78 / 10.0; + if (!wlf_handle_wheel(instance, ev->mouse_axis.x, ev->mouse_axis.y, + ev->mouse_axis.axis, val)) + success = FALSE; + } + break; + default: + break; + } + } + } + ArrayList_Clear(context->events); + return success; +} + +BOOL wlf_handle_pointer_source(freerdp* instance, const UwacPointerSourceEvent* ev) +{ + wlfContext* context; + if (!instance || !instance->context || !ev) + return FALSE; + + context = (wlfContext*)instance->context; + ArrayList_Add(context->events, ev); return TRUE; } diff --git a/client/Wayland/wlf_input.h b/client/Wayland/wlf_input.h index 2382dd8..ff41300 100644 --- a/client/Wayland/wlf_input.h +++ b/client/Wayland/wlf_input.h @@ -30,6 +30,9 @@ BOOL wlf_handle_pointer_enter(freerdp* instance, const UwacPointerEnterLeaveEven BOOL wlf_handle_pointer_motion(freerdp* instance, const UwacPointerMotionEvent* ev); BOOL wlf_handle_pointer_buttons(freerdp* instance, const UwacPointerButtonEvent* ev); BOOL wlf_handle_pointer_axis(freerdp* instance, const UwacPointerAxisEvent* ev); +BOOL wlf_handle_pointer_axis_discrete(freerdp* instance, const UwacPointerAxisEvent* ev); +BOOL wlf_handle_pointer_frame(freerdp* instance, const UwacPointerFrameEvent* ev); +BOOL wlf_handle_pointer_source(freerdp* instance, const UwacPointerSourceEvent* ev); BOOL wlf_handle_touch_up(freerdp* instance, const UwacTouchUp* ev); BOOL wlf_handle_touch_down(freerdp* instance, const UwacTouchDown* ev); BOOL wlf_handle_touch_motion(freerdp* instance, const UwacTouchMotion* ev); diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index c7a9fca..65e29bc 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -362,12 +362,22 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display) break; case UWAC_EVENT_POINTER_AXIS: + if (!wlf_handle_pointer_axis(instance, &event.mouse_axis)) + return FALSE; break; case UWAC_EVENT_POINTER_AXIS_DISCRETE: - if (!wlf_handle_pointer_axis(instance, &event.mouse_axis)) + if (!wlf_handle_pointer_axis_discrete(instance, &event.mouse_axis)) return FALSE; + break; + case UWAC_EVENT_POINTER_FRAME: + if (!wlf_handle_pointer_frame(instance, &event.mouse_frame)) + return FALSE; + break; + case UWAC_EVENT_POINTER_SOURCE: + if (!wlf_handle_pointer_source(instance, &event.mouse_source)) + return FALSE; break; case UWAC_EVENT_KEY: @@ -561,8 +571,37 @@ static int wlf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type) return 1; } +static void wlf_client_free(freerdp* instance, rdpContext* context) +{ + wlfContext* wlf = (wlfContext*)instance->context; + + if (!context) + return; + + if (wlf->display) + UwacCloseDisplay(&wlf->display); + + if (wlf->displayHandle) + CloseHandle(wlf->displayHandle); + ArrayList_Free(wlf->events); + DeleteCriticalSection(&wlf->critical); +} + +static void* uwac_event_clone(const void* val) +{ + UwacEvent* copy; + UwacEvent* ev = (UwacEvent*)val; + + copy = calloc(1, sizeof(UwacEvent)); + if (!copy) + return NULL; + *copy = *ev; + return copy; +} + static BOOL wlf_client_new(freerdp* instance, rdpContext* context) { + wObject* obj; UwacReturnCode status; wlfContext* wfl = (wlfContext*)context; @@ -590,26 +629,19 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context) if (!wfl->displayHandle) return FALSE; + wfl->events = ArrayList_New(FALSE); + if (!wfl->events) + return FALSE; + + obj = ArrayList_Object(wfl->events); + obj->fnObjectNew = uwac_event_clone; + obj->fnObjectFree = free; + InitializeCriticalSection(&wfl->critical); return TRUE; } -static void wlf_client_free(freerdp* instance, rdpContext* context) -{ - wlfContext* wlf = (wlfContext*)instance->context; - - if (!context) - return; - - if (wlf->display) - UwacCloseDisplay(&wlf->display); - - if (wlf->displayHandle) - CloseHandle(wlf->displayHandle); - DeleteCriticalSection(&wlf->critical); -} - static int wfl_client_start(rdpContext* context) { WINPR_UNUSED(context); diff --git a/client/Wayland/wlfreerdp.h b/client/Wayland/wlfreerdp.h index d84f91c..6af13bb 100644 --- a/client/Wayland/wlfreerdp.h +++ b/client/Wayland/wlfreerdp.h @@ -53,6 +53,7 @@ struct wlf_context wlfDispContext* disp; wLog* log; CRITICAL_SECTION critical; + wArrayList* events; }; BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP); diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index 4f52853..aecd389 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -1066,7 +1066,7 @@ static BOOL xf_gdi_surface_bits(rdpContext* context, const SURFACE_BITS_COMMAND* case RDP_CODEC_ID_NONE: pSrcData = cmd->bmp.bitmapData; format = gdi_get_pixel_format(cmd->bmp.bpp); - size = cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format) * 1ULL; + size = 1ull * cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format); if (size > cmd->bmp.bitmapDataLength) { WLog_ERR(TAG, "Short nocodec message: got %" PRIu32 " bytes, require %" PRIuz, diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 97d3ad3..3863d66 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -288,7 +288,7 @@ static UINT xf_CreateSurface(RdpgfxClientContext* context, surface->gdi.scanline = surface->gdi.width * GetBytesPerPixel(surface->gdi.format); surface->gdi.scanline = x11_pad_scanline(surface->gdi.scanline, xfc->scanline_pad); - size = surface->gdi.scanline * surface->gdi.height * 1ULL; + size = 1ull * surface->gdi.scanline * surface->gdi.height; surface->gdi.data = (BYTE*)_aligned_malloc(size, 16); if (!surface->gdi.data) @@ -312,7 +312,7 @@ static UINT xf_CreateSurface(RdpgfxClientContext* context, UINT32 bytes = GetBytesPerPixel(gdi->dstFormat); surface->stageScanline = width * bytes; surface->stageScanline = x11_pad_scanline(surface->stageScanline, xfc->scanline_pad); - size = surface->stageScanline * surface->gdi.height * 1ULL; + size = 1ull * surface->stageScanline * surface->gdi.height; surface->stage = (BYTE*)_aligned_malloc(size, 16); if (!surface->stage) diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index 82b0b95..5aa1fd4 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -311,7 +311,7 @@ static BOOL xf_Pointer_GetCursorForCurrentScale(rdpContext* context, const rdpPo ci.height = yTargetSize; ci.xhot = pointer->xPos * xscale; ci.yhot = pointer->yPos * yscale; - size = ci.height * ci.width * GetBytesPerPixel(CursorFormat) * 1ULL; + size = 1ull * ci.height * ci.width * GetBytesPerPixel(CursorFormat); if (!(ci.pixels = (XcursorPixel*)_aligned_malloc(size, 16))) { @@ -421,7 +421,7 @@ static BOOL xf_Pointer_New(rdpContext* context, rdpPointer* pointer) xpointer->nCursors = 0; xpointer->mCursors = 0; - size = pointer->height * pointer->width * GetBytesPerPixel(CursorFormat) * 1ULL; + size = 1ull * pointer->height * pointer->width * GetBytesPerPixel(CursorFormat); if (!(xpointer->cursorPixels = (XcursorPixel*)_aligned_malloc(size, 16))) goto fail; @@ -560,7 +560,7 @@ static BOOL xf_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y) } WLog_DBG(TAG, "%s: %" PRIu32 "x%" PRIu32, __func__, x, y); - if (xfc->remote_app && !xfc->focused) + if (!xfc->focused) return TRUE; xf_adjust_coordinates_to_screen(xfc, &x, &y); @@ -583,7 +583,7 @@ static BOOL xf_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y) goto out; } - rc = XWarpPointer(xfc->display, None, handle, 0, 0, 0, 0, x, y); + rc = XWarpPointer(xfc->display, handle, handle, 0, 0, 0, 0, x, y); if (rc == 0) WLog_WARN(TAG, "%s: XWarpPointer==%d", __func__, rc); tmp.event_mask = current.your_event_mask; diff --git a/client/X11/xf_rail.c b/client/X11/xf_rail.c index 090f599..6995bdd 100644 --- a/client/X11/xf_rail.c +++ b/client/X11/xf_rail.c @@ -544,7 +544,7 @@ static xfRailIconCache* RailIconCache_New(rdpSettings* settings) cache->numCaches = settings->RemoteAppNumIconCaches; cache->numCacheEntries = settings->RemoteAppNumIconCacheEntries; - cache->entries = calloc(cache->numCaches * cache->numCacheEntries * 1ULL, sizeof(xfRailIcon)); + cache->entries = calloc(1ull * cache->numCaches * cache->numCacheEntries, sizeof(xfRailIcon)); if (!cache->entries) { @@ -614,7 +614,7 @@ static BOOL convert_rail_icon(const ICON_INFO* iconInfo, xfRailIcon* railIcon) long* pixels; int i; int nelements; - argbPixels = calloc(iconInfo->width * iconInfo->height * 1ULL, 4); + argbPixels = calloc(1ull * iconInfo->width * iconInfo->height, 4); if (!argbPixels) goto error; diff --git a/client/common/cmdline.c b/client/common/cmdline.c index d2d949b..19ece39 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -2996,6 +2996,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { settings->GrabKeyboard = enable; } + CommandLineSwitchCase(arg, "grab-mouse") + { + settings->GrabMouse = enable; + } CommandLineSwitchCase(arg, "unmap-buttons") { settings->UnmapButtons = enable; diff --git a/client/common/cmdline.h b/client/common/cmdline.h index 92a86f9..6ecc8c5 100644 --- a/client/common/cmdline.h +++ b/client/common/cmdline.h @@ -184,6 +184,7 @@ static const COMMAND_LINE_ARGUMENT_A args[] = { { "gp", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Gateway password" }, { "grab-keyboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Grab keyboard" }, + { "grab-mouse", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Grab mouse" }, { "gt", COMMAND_LINE_VALUE_REQUIRED, "[rpc|http[,no-websockets]|auto[,no-websockets]]", NULL, NULL, -1, NULL, "Gateway transport type" }, { "gu", COMMAND_LINE_VALUE_REQUIRED, "[[\\]|[@]]", NULL, NULL, -1, diff --git a/cmake/FindOpenSSL.cmake b/cmake/FindOpenSSL.cmake index d42a50c..f630d1a 100644 --- a/cmake/FindOpenSSL.cmake +++ b/cmake/FindOpenSSL.cmake @@ -55,7 +55,7 @@ FIND_PATH(OPENSSL_INCLUDE_DIR NAMES openssl/ssl.h PATH_SUFFIXES - "include" + "include" HINTS ${_OPENSSL_INCLUDEDIR} ${_OPENSSL_ROOT_HINTS_AND_PATHS} @@ -172,8 +172,8 @@ ELSEIF(WIN32 AND NOT CYGWIN) ) set( OPENSSL_DEBUG_LIBRARIES ${SSL_EAY_DEBUG} ${LIB_EAY_DEBUG} ) - set( OPENSSL_RELEASE_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} ) - set( OPENSSL_LIBRARIES ${OPENSSL_RELEASE_LIBRARIES} ) + set( OPENSSL_RELEASE_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} ) + set( OPENSSL_LIBRARIES ${OPENSSL_RELEASE_LIBRARIES} ) MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE) MARK_AS_ADVANCED(LIB_EAY_DEBUG LIB_EAY_RELEASE) @@ -313,25 +313,50 @@ if (OPENSSL_INCLUDE_DIR) string(REGEX REPLACE "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F]).*$" "\\1;\\2;\\3;\\4;\\5" OPENSSL_VERSION_LIST "${openssl_version_str}") - list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR) - list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR) - from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR) - list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX) - from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX) - list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH) + if (OPENSSL_VERSION_LIST) + list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR) + list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR) + from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR) + list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX) + from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX) + list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH) - if (NOT OPENSSL_VERSION_PATCH STREQUAL "00") - from_hex("${OPENSSL_VERSION_PATCH}" _tmp) - # 96 is the ASCII code of 'a' minus 1 - math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96") - unset(_tmp) - # Once anyone knows how OpenSSL would call the patch versions beyond 'z' - # this should be updated to handle that, too. This has not happened yet - # so it is simply ignored here for now. - string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING) - endif (NOT OPENSSL_VERSION_PATCH STREQUAL "00") + if (NOT OPENSSL_VERSION_PATCH STREQUAL "00") + from_hex("${OPENSSL_VERSION_PATCH}" _tmp) + # 96 is the ASCII code of 'a' minus 1 + math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96") + unset(_tmp) + # Once anyone knows how OpenSSL would call the patch versions beyond 'z' + # this should be updated to handle that, too. This has not happened yet + # so it is simply ignored here for now. + string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING) + endif (NOT OPENSSL_VERSION_PATCH STREQUAL "00") - set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}") + set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}") + endif() + + if (NOT OPENSSL_VERSION_LIST) + file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str_str + REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_STR[\t ]\"([0-9a-fA-F]+)\\.([0-9a-fA-F]+)\\.([0-9a-fA-F]+).*\".*$") + string(REGEX REPLACE "^.*OPENSSL_VERSION_STR[\t ]+\"([0-9a-fA-F]+)\\.([0-9a-fA-F]+)\\.([0-9a-fA-F]+).*\".*$" + "\\1.\\2.\\3" OPENSSL_VERSION "${openssl_version_str_str}") + endif() + + if (NOT OPENSSL_VERSION_LIST) + file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_major_str + REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_MAJOR[\t ]+([0-9a-fA-F]+).*$") + string(REGEX REPLACE "^#[\t ]*define[\t ]+OPENSSL_VERSION_MAJOR[\t ]+([0-9a-fA-F]+).*$" + "\\1" OPENSSL_VERSION_MAJOR "${openssl_version_major_str}") + file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_minor_str + REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_MINOR[\t ]+([0-9a-fA-F]+).*$") + string(REGEX REPLACE "^#[\t ]*define[\t ]+OPENSSL_VERSION_MINOR[\t ]+([0-9a-fA-F]+).*$" + "\\1" OPENSSL_VERSION_MINOR "${openssl_version_minor_str}") + file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_patch_str + REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_PATCH[\t ]+([0-9a-fA-F]+).*$") + string(REGEX REPLACE "^#[\t ]*define[\t ]+OPENSSL_VERSION_PATCH[\t ]+([0-9a-fA-F]+).*$" + "\\1" OPENSSL_VERSION_PATCH "${openssl_version_patch_str}") + set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_PATCH}") + endif() endif (_OPENSSL_VERSION) endif (OPENSSL_INCLUDE_DIR) diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 4268efd..76f1951 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -730,6 +730,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL; #define FreeRDP_PercentScreenUseWidth (1556) #define FreeRDP_PercentScreenUseHeight (1557) #define FreeRDP_DynamicResolutionUpdate (1558) +#define FreeRDP_GrabMouse (1559) #define FreeRDP_SoftwareGdi (1601) #define FreeRDP_LocalConnection (1602) #define FreeRDP_AuthenticationOnly (1603) @@ -1216,7 +1217,8 @@ struct rdp_settings ALIGN64 BOOL PercentScreenUseWidth; /* 1556 */ ALIGN64 BOOL PercentScreenUseHeight; /* 1557 */ ALIGN64 BOOL DynamicResolutionUpdate; /* 1558 */ - UINT64 padding1601[1601 - 1559]; /* 1559 */ + ALIGN64 BOOL GrabMouse; /* 1559 */ + UINT64 padding1601[1601 - 1560]; /* 1560 */ /* Miscellaneous */ ALIGN64 BOOL SoftwareGdi; /* 1601 */ diff --git a/libfreerdp/cache/pointer.c b/libfreerdp/cache/pointer.c index 010df17..42acf65 100644 --- a/libfreerdp/cache/pointer.c +++ b/libfreerdp/cache/pointer.c @@ -68,6 +68,9 @@ static BOOL update_pointer_position(rdpContext* context, !pointer_position) return FALSE; + if (!context->settings->GrabMouse) + return TRUE; + pointer = context->graphics->Pointer_Prototype; return IFCALLRESULT(TRUE, pointer->SetPosition, context, pointer_position->xPos, pointer_position->yPos); diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c index fadd98e..1012607 100644 --- a/libfreerdp/codec/clear.c +++ b/libfreerdp/codec/clear.c @@ -566,7 +566,7 @@ static BOOL resize_vbar_entry(CLEAR_CONTEXT* clear, CLEAR_VBAR_ENTRY* vBarEntry) const UINT32 diffSize = (vBarEntry->count - vBarEntry->size) * bpp; BYTE* tmp; vBarEntry->size = vBarEntry->count; - tmp = (BYTE*)realloc(vBarEntry->pixels, vBarEntry->count * bpp * 1ULL); + tmp = (BYTE*)realloc(vBarEntry->pixels, 1ull * vBarEntry->count * bpp); if (!tmp) { @@ -591,13 +591,9 @@ static BOOL resize_vbar_entry(CLEAR_CONTEXT* clear, CLEAR_VBAR_ENTRY* vBarEntry) static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 bandsByteCount, UINT32 nWidth, UINT32 nHeight, BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, - UINT32 nYDst) + UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight) { - UINT32 i, y; - UINT32 count; - UINT32 suboffset; - UINT32 nXDstRel; - UINT32 nYDstRel; + UINT32 suboffset = 0; if (Stream_GetRemainingLength(s) < bandsByteCount) { @@ -605,22 +601,20 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 return FALSE; } - suboffset = 0; - while (suboffset < bandsByteCount) { - BYTE r, g, b; + BYTE cr, cg, cb; UINT16 xStart; UINT16 xEnd; UINT16 yStart; UINT16 yEnd; UINT32 colorBkg; UINT16 vBarHeader; - UINT16 vBarYOn; + UINT16 vBarYOn = 0; UINT16 vBarYOff; UINT32 vBarCount; UINT32 vBarPixelCount; - UINT32 vBarShortPixelCount; + UINT32 vBarShortPixelCount = 0; if (Stream_GetRemainingLength(s) < 11) { @@ -632,11 +626,11 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 Stream_Read_UINT16(s, xEnd); Stream_Read_UINT16(s, yStart); Stream_Read_UINT16(s, yEnd); - Stream_Read_UINT8(s, b); - Stream_Read_UINT8(s, g); - Stream_Read_UINT8(s, r); + Stream_Read_UINT8(s, cb); + Stream_Read_UINT8(s, cg); + Stream_Read_UINT8(s, cr); suboffset += 11; - colorBkg = FreeRDPGetColor(clear->format, r, g, b, 0xFF); + colorBkg = FreeRDPGetColor(clear->format, cr, cg, cb, 0xFF); if (xEnd < xStart) { @@ -652,13 +646,13 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 vBarCount = (xEnd - xStart) + 1; - for (i = 0; i < vBarCount; i++) + for (UINT32 i = 0; i < vBarCount; i++) { UINT32 vBarHeight; CLEAR_VBAR_ENTRY* vBarEntry = NULL; - CLEAR_VBAR_ENTRY* vBarShortEntry; + CLEAR_VBAR_ENTRY* vBarShortEntry = NULL; BOOL vBarUpdate = FALSE; - const BYTE* pSrcPixel; + const BYTE* cpSrcPixel; if (Stream_GetRemainingLength(s) < 2) { @@ -740,11 +734,11 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 if (!resize_vbar_entry(clear, vBarShortEntry)) return FALSE; - for (y = 0; y < vBarShortPixelCount; y++) + for (UINT32 y = 0; y < vBarShortPixelCount; y++) { - BYTE r, g, b; + BYTE r = 0, g = 0, b = 0; BYTE* dstBuffer = &vBarShortEntry->pixels[y * GetBytesPerPixel(clear->format)]; - UINT32 color; + UINT32 color = 0; Stream_Read_UINT8(s, b); Stream_Read_UINT8(s, g); Stream_Read_UINT8(s, r); @@ -804,8 +798,8 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 dstBuffer = vBarEntry->pixels; /* if (y < vBarYOn), use colorBkg */ - y = 0; - count = vBarYOn; + UINT32 y = 0; + UINT32 count = vBarYOn; if ((y + count) > vBarPixelCount) count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0; @@ -868,28 +862,31 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 return FALSE; } - nXDstRel = nXDst + xStart; - nYDstRel = nYDst + yStart; - pSrcPixel = vBarEntry->pixels; + const UINT32 nXDstRel = nXDst + xStart; + const UINT32 nYDstRel = nYDst + yStart; + cpSrcPixel = vBarEntry->pixels; if (i < nWidth) { - count = vBarEntry->count; + UINT32 count = vBarEntry->count; if (count > nHeight) count = nHeight; - for (y = 0; y < count; y++) + if (nXDstRel + i > nDstWidth) + return FALSE; + + for (UINT32 y = 0; y < count; y++) { BYTE* pDstPixel8 = &pDstData[((nYDstRel + y) * nDstStep) + ((nXDstRel + i) * GetBytesPerPixel(DstFormat))]; - UINT32 color = ReadColor(pSrcPixel, clear->format); + UINT32 color = ReadColor(cpSrcPixel, clear->format); color = FreeRDPConvertColor(color, clear->format, DstFormat, NULL); if (!WriteColor(pDstPixel8, DstFormat, color)) return FALSE; - pSrcPixel += GetBytesPerPixel(clear->format); + cpSrcPixel += GetBytesPerPixel(clear->format); } } } @@ -980,7 +977,7 @@ static BOOL clear_decompress_glyph_data(CLEAR_CONTEXT* clear, wStream* s, UINT32 if (glyphEntry->count > glyphEntry->size) { BYTE* tmp; - tmp = realloc(glyphEntry->pixels, glyphEntry->count * bpp * 1ULL); + tmp = realloc(glyphEntry->pixels, 1ull * glyphEntry->count * bpp); if (!tmp) { @@ -1117,7 +1114,7 @@ INT32 clear_decompress(CLEAR_CONTEXT* clear, const BYTE* pSrcData, UINT32 SrcSiz if (bandsByteCount > 0) { if (!clear_decompress_bands_data(clear, s, bandsByteCount, nWidth, nHeight, pDstData, - DstFormat, nDstStep, nXDst, nYDst)) + DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight)) { WLog_ERR(TAG, "clear_decompress_bands_data failed!"); goto fail; diff --git a/libfreerdp/codec/color.c b/libfreerdp/codec/color.c index edbfcd4..0091998 100644 --- a/libfreerdp/codec/color.c +++ b/libfreerdp/codec/color.c @@ -56,7 +56,7 @@ BYTE* freerdp_glyph_convert(UINT32 width, UINT32 height, const BYTE* data) * means of accessing individual pixels in blitting operations */ scanline = (width + 7) / 8; - dstData = (BYTE*)_aligned_malloc(width * height * 1ULL, 16); + dstData = (BYTE*)_aligned_malloc(1ull * width * height, 16); if (!dstData) return NULL; @@ -545,7 +545,7 @@ BOOL freerdp_image_copy_from_pointer_data(BYTE* pDstData, UINT32 DstFormat, UINT for (y = nYDst; y < nHeight; y++) { BYTE* pDstLine = &pDstData[y * nDstStep + nXDst * dstBytesPerPixel]; - memset(pDstLine, 0, dstBytesPerPixel * (nWidth - nXDst) * 1ULL); + memset(pDstLine, 0, 1ull * dstBytesPerPixel * (nWidth - nXDst)); } switch (xorBpp) @@ -728,21 +728,22 @@ BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 BOOL freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color) { - UINT32 x, y; + if ((nWidth == 0) || (nHeight == 0)) + return TRUE; const UINT32 bpp = GetBytesPerPixel(DstFormat); BYTE* pFirstDstLine = &pDstData[nYDst * nDstStep]; BYTE* pFirstDstLineXOffset = &pFirstDstLine[nXDst * bpp]; - for (x = 0; x < nWidth; x++) + for (UINT32 x = 0; x < nWidth; x++) { BYTE* pDst = &pFirstDstLine[(x + nXDst) * bpp]; WriteColor(pDst, DstFormat, color); } - for (y = 1; y < nHeight; y++) + for (UINT32 y = 1; y < nHeight; y++) { BYTE* pDstLine = &pDstData[(y + nYDst) * nDstStep + nXDst * bpp]; - memcpy(pDstLine, pFirstDstLineXOffset, nWidth * bpp * 1ULL); + memcpy(pDstLine, pFirstDstLineXOffset, 1ull * nWidth * bpp); } return TRUE; diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c index 36b5a7c..3f1ddb3 100644 --- a/libfreerdp/codec/h264.c +++ b/libfreerdp/codec/h264.c @@ -63,9 +63,9 @@ BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT3 _aligned_free(h264->pYUVData[0]); _aligned_free(h264->pYUVData[1]); _aligned_free(h264->pYUVData[2]); - h264->pYUVData[0] = _aligned_malloc(h264->iStride[0] * height * 1ULL, 16); - h264->pYUVData[1] = _aligned_malloc(h264->iStride[1] * height * 1ULL, 16); - h264->pYUVData[2] = _aligned_malloc(h264->iStride[2] * height * 1ULL, 16); + h264->pYUVData[0] = _aligned_malloc(1ull * h264->iStride[0] * height, 16); + h264->pYUVData[1] = _aligned_malloc(1ull * h264->iStride[1] * height, 16); + h264->pYUVData[2] = _aligned_malloc(1ull * h264->iStride[2] * height, 16); if (!h264->pYUVData[0] || !h264->pYUVData[1] || !h264->pYUVData[2]) return FALSE; diff --git a/libfreerdp/codec/h264_ffmpeg.c b/libfreerdp/codec/h264_ffmpeg.c index 4e3ba8f..9c445b8 100644 --- a/libfreerdp/codec/h264_ffmpeg.c +++ b/libfreerdp/codec/h264_ffmpeg.c @@ -529,10 +529,12 @@ static BOOL libavcodec_init(H264_CONTEXT* h264) goto EXCEPTION; } +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100) if (sys->codecDecoder->capabilities & AV_CODEC_CAP_TRUNCATED) { sys->codecDecoderContext->flags |= AV_CODEC_FLAG_TRUNCATED; } +#endif #ifdef WITH_VAAPI diff --git a/libfreerdp/codec/ncrush.c b/libfreerdp/codec/ncrush.c index 3d6a216..c1d622a 100644 --- a/libfreerdp/codec/ncrush.c +++ b/libfreerdp/codec/ncrush.c @@ -1994,15 +1994,9 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY UINT32* pDstSize, UINT32 flags) { UINT32 index; - UINT32 bits; - INT32 nbits; - const BYTE* SrcPtr; - const BYTE* SrcEnd; - UINT16 Mask; BYTE Literal; UINT32 IndexLEC; UINT32 BitLength; - UINT32 MaskedBits; UINT32 CopyOffset; UINT32 CopyLength; UINT32 OldCopyOffset; @@ -2010,9 +2004,6 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY UINT32 LengthOfMatch; UINT32 CopyOffsetIndex; UINT32 OffsetCacheIndex; - BYTE* HistoryPtr; - BYTE* HistoryBuffer; - BYTE* HistoryBufferEnd; UINT32 CopyOffsetBits; UINT32 CopyOffsetBase; UINT32 LengthOfMatchBits; @@ -2021,8 +2012,8 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY if (ncrush->HistoryEndOffset != 65535) return -1001; - HistoryBuffer = ncrush->HistoryBuffer; - HistoryBufferEnd = &HistoryBuffer[ncrush->HistoryEndOffset]; + BYTE* HistoryBuffer = ncrush->HistoryBuffer; + const BYTE* HistoryBufferEnd = &HistoryBuffer[ncrush->HistoryEndOffset]; if (flags & PACKET_AT_FRONT) { @@ -2041,7 +2032,7 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache)); } - HistoryPtr = ncrush->HistoryPtr; + BYTE* HistoryPtr = ncrush->HistoryPtr; if (!(flags & PACKET_COMPRESSED)) { @@ -2050,17 +2041,19 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY return 1; } - SrcEnd = &pSrcData[SrcSize]; - nbits = 32; - bits = get_dword(pSrcData); - SrcPtr = pSrcData + 4; + const BYTE* SrcEnd = &pSrcData[SrcSize]; + const BYTE* SrcPtr = pSrcData + 4; + INT32 nbits = 32; + UINT32 bits = get_dword(pSrcData); while (1) { while (1) { - Mask = get_word(&HuffTableMask[29]); - MaskedBits = bits & Mask; + const UINT16 Mask = get_word(&HuffTableMask[29]); + const UINT32 MaskedBits = bits & Mask; + if (MaskedBits >= ARRAYSIZE(HuffTableLEC)) + return -1; IndexLEC = HuffTableLEC[MaskedBits] & 0xFFF; BitLength = HuffTableLEC[MaskedBits] >> 12; bits >>= BitLength; @@ -2096,8 +2089,10 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY return -1004; CopyOffset = ncrush->OffsetCache[OffsetCacheIndex]; - Mask = get_word(&HuffTableMask[21]); - MaskedBits = bits & Mask; + const UINT16 Mask = get_word(&HuffTableMask[21]); + const UINT32 MaskedBits = bits & Mask; + if (MaskedBits > ARRAYSIZE(HuffTableLOM)) + return -1; LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF; BitLength = HuffTableLOM[MaskedBits] >> 12; bits >>= BitLength; @@ -2106,13 +2101,23 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits)) return -1; + if (LengthOfMatch >= ARRAYSIZE(LOMBitsLUT)) + return -1; + LengthOfMatchBits = LOMBitsLUT[LengthOfMatch]; + + if (LengthOfMatch >= ARRAYSIZE(LOMBaseLUT)) + return -1; LengthOfMatchBase = LOMBaseLUT[LengthOfMatch]; if (LengthOfMatchBits) { - Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]); - MaskedBits = bits & Mask; + const size_t idx = (2ull * LengthOfMatchBits) + 3ull; + if (idx >= ARRAYSIZE(HuffTableMask)) + return -1; + + const UINT16 Mask = get_word(&HuffTableMask[idx]); + const UINT32 MaskedBits = bits & Mask; bits >>= LengthOfMatchBits; nbits -= LengthOfMatchBits; LengthOfMatchBase += MaskedBits; @@ -2127,15 +2132,28 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY } else { + if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBitsLUT)) + return -1; + CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex]; + + if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBaseLUT)) + return -1; CopyOffsetBase = CopyOffsetBaseLUT[CopyOffsetIndex]; CopyOffset = CopyOffsetBase - 1; if (CopyOffsetBits) { - Mask = get_word(&HuffTableMask[(2 * CopyOffsetBits) + 3]); - MaskedBits = bits & Mask; - CopyOffset = CopyOffsetBase + MaskedBits - 1; + const size_t idx = (2ull * CopyOffsetBits) + 3ull; + if (idx >= ARRAYSIZE(HuffTableMask)) + return -1; + + const UINT16 Mask = get_word(&HuffTableMask[idx]); + const UINT32 MaskedBits = bits & Mask; + const UINT32 tmp = CopyOffsetBase + MaskedBits; + if (tmp < 1) + return -1; + CopyOffset = tmp - 1; bits >>= CopyOffsetBits; nbits -= CopyOffsetBits; @@ -2143,8 +2161,11 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY return -1; } - Mask = get_word(&HuffTableMask[21]); - MaskedBits = bits & Mask; + const UINT16 Mask = get_word(&HuffTableMask[21]); + const UINT32 MaskedBits = bits & Mask; + if (MaskedBits >= ARRAYSIZE(HuffTableLOM)) + return -1; + LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF; BitLength = HuffTableLOM[MaskedBits] >> 12; bits >>= BitLength; @@ -2153,13 +2174,23 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY if (!NCrushFetchBits(&SrcPtr, &SrcEnd, &nbits, &bits)) return -1; + if (LengthOfMatch >= ARRAYSIZE(LOMBitsLUT)) + return -1; + LengthOfMatchBits = LOMBitsLUT[LengthOfMatch]; + + if (LengthOfMatch >= ARRAYSIZE(LOMBaseLUT)) + return -1; LengthOfMatchBase = LOMBaseLUT[LengthOfMatch]; if (LengthOfMatchBits) { - Mask = get_word(&HuffTableMask[(2 * LengthOfMatchBits) + 3]); - MaskedBits = bits & Mask; + const size_t idx = (2ull * LengthOfMatchBits) + 3ull; + if (idx >= ARRAYSIZE(HuffTableMask)) + return -1; + + const UINT16 Mask = get_word(&HuffTableMask[idx]); + const UINT32 MaskedBits = bits & Mask; bits >>= LengthOfMatchBits; nbits -= LengthOfMatchBits; LengthOfMatchBase += MaskedBits; @@ -2583,7 +2614,12 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE } IndexLEC = Literal; + if (IndexLEC >= ARRAYSIZE(HuffLengthLEC)) + return -1; BitLength = HuffLengthLEC[IndexLEC]; + + if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC)) + return -1; CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); if (BitLength > 15) @@ -2666,9 +2702,18 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE bits = CopyOffset; CopyOffsetIndex = ncrush->HuffTableCopyOffset[bits + 2]; + + if (CopyOffsetIndex >= ARRAYSIZE(CopyOffsetBitsLUT)) + return -1; + CopyOffsetBits = CopyOffsetBitsLUT[CopyOffsetIndex]; IndexLEC = 257 + CopyOffsetIndex; + if (IndexLEC >= ARRAYSIZE(HuffLengthLEC)) + return -1; BitLength = HuffLengthLEC[IndexLEC]; + + if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC)) + return -1; CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); if (BitLength > 15) @@ -2687,13 +2732,23 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE else IndexCO = ncrush->HuffTableLOM[MatchLength]; + if (IndexCO >= ARRAYSIZE(HuffLengthLOM)) + return -1; BitLength = HuffLengthLOM[IndexCO]; + + if (IndexCO >= ARRAYSIZE(LOMBitsLUT)) + return -1; IndexLOM = LOMBitsLUT[IndexCO]; + + if (IndexCO >= ARRAYSIZE(HuffCodeLOM)) + return -1; NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength); Mask = ((1 << IndexLOM) - 1); MaskedBits = (MatchLength - 2) & Mask; NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM); + if (IndexCO >= ARRAYSIZE(LOMBaseLUT)) + return -1; if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength) return -1010; } @@ -2701,7 +2756,11 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE { /* CopyOffset in OffsetCache */ IndexLEC = 289 + OffsetCacheIndex; + if (IndexLEC >= ARRAYSIZE(HuffLengthLEC)) + return -1; BitLength = HuffLengthLEC[IndexLEC]; + if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC)) + return -1; CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); if (BitLength >= 15) @@ -2714,13 +2773,24 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE else IndexCO = ncrush->HuffTableLOM[MatchLength]; + if (IndexCO >= ARRAYSIZE(HuffLengthLOM)) + return -1; + BitLength = HuffLengthLOM[IndexCO]; + + if (IndexCO >= ARRAYSIZE(LOMBitsLUT)) + return -1; IndexLOM = LOMBitsLUT[IndexCO]; + + if (IndexCO >= ARRAYSIZE(HuffCodeLOM)) + return -1; NCrushWriteBits(&DstPtr, &accumulator, &offset, HuffCodeLOM[IndexCO], BitLength); Mask = ((1 << IndexLOM) - 1); MaskedBits = (MatchLength - 2) & Mask; NCrushWriteBits(&DstPtr, &accumulator, &offset, MaskedBits, IndexLOM); + if (IndexCO >= ARRAYSIZE(LOMBaseLUT)) + return -1; if ((MaskedBits + LOMBaseLUT[IndexCO]) != MatchLength) return -1012; } @@ -2745,6 +2815,10 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE Literal = *SrcPtr++; HistoryPtr++; IndexLEC = Literal; + if (IndexLEC >= ARRAYSIZE(HuffLengthLEC)) + return -1; + if (IndexLEC * 2ull >= ARRAYSIZE(HuffCodeLEC)) + return -1; BitLength = HuffLengthLEC[IndexLEC]; CodeLEC = get_word(&HuffCodeLEC[IndexLEC * 2]); @@ -2817,6 +2891,11 @@ static int ncrush_generate_tables(NCRUSH_CONTEXT* context) else i = context->HuffTableLOM[k]; + if (i >= ARRAYSIZE(LOMBitsLUT)) + return -1; + if (i >= ARRAYSIZE(LOMBaseLUT)) + return -1; + if (((((1 << LOMBitsLUT[i]) - 1) & (k - 2)) + LOMBaseLUT[i]) != k) return -1; } diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c index dc3a978..645ca75 100644 --- a/libfreerdp/codec/nsc.c +++ b/libfreerdp/codec/nsc.c @@ -29,6 +29,8 @@ #include #include +#include +#include #include #include @@ -38,6 +40,12 @@ #include "nsc_sse2.h" +#if !defined(Stream_CheckAndLogRequiredLengthWLog) +#define Stream_CheckAndLogRequiredLengthWLog(log, s, len) \ + Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, "%s(%s:%d)", __FUNCTION__, \ + __FILE__, __LINE__) +#endif + #ifndef NSC_INIT_SIMD #define NSC_INIT_SIMD(_nsc_context) \ do \ @@ -111,12 +119,17 @@ static BOOL nsc_decode(NSC_CONTEXT* context) return TRUE; } -static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalSize) +static BOOL nsc_rle_decode(const BYTE* in, size_t inSize, BYTE* out, UINT32 outSize, + UINT32 originalSize) { UINT32 left = originalSize; while (left > 4) { + if (inSize < 1) + return FALSE; + inSize--; + const BYTE value = *in++; UINT32 len = 0; @@ -129,17 +142,26 @@ static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalS *out++ = value; left--; } + else if (inSize < 1) + return FALSE; else if (value == *in) { + inSize--; in++; - if (*in < 0xFF) + if (inSize < 1) + return FALSE; + else if (*in < 0xFF) { + inSize--; len = (UINT32)*in++; len += 2; } else { + if (inSize < 5) + return FALSE; + inSize -= 5; in++; len = ((UINT32)(*in++)); len |= ((UINT32)(*in++)) << 8U; @@ -169,26 +191,28 @@ static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalS if ((outSize < 4) || (left < 4)) return FALSE; + if (inSize < 4) + return FALSE; memcpy(out, in, 4); return TRUE; } static BOOL nsc_rle_decompress_data(NSC_CONTEXT* context) { - UINT16 i; - BYTE* rle; - UINT32 planeSize; - UINT32 originalSize; - if (!context) return FALSE; - rle = context->Planes; + const BYTE* rle = context->Planes; + size_t rleSize = context->PlanesSize; + WINPR_ASSERT(rle); - for (i = 0; i < 4; i++) + for (size_t i = 0; i < 4; i++) { - originalSize = context->OrgByteCount[i]; - planeSize = context->PlaneByteCount[i]; + const UINT32 originalSize = context->OrgByteCount[i]; + const UINT32 planeSize = context->PlaneByteCount[i]; + + if (rleSize < planeSize) + return FALSE; if (planeSize == 0) { @@ -199,7 +223,7 @@ static BOOL nsc_rle_decompress_data(NSC_CONTEXT* context) } else if (planeSize < originalSize) { - if (!nsc_rle_decode(rle, context->priv->PlaneBuffers[i], + if (!nsc_rle_decode(rle, rleSize, context->priv->PlaneBuffers[i], context->priv->PlaneBuffersLength, originalSize)) return FALSE; } @@ -208,6 +232,9 @@ static BOOL nsc_rle_decompress_data(NSC_CONTEXT* context) if (context->priv->PlaneBuffersLength < originalSize) return FALSE; + if (rleSize < originalSize) + return FALSE; + CopyMemory(context->priv->PlaneBuffers[i], rle, originalSize); } @@ -219,64 +246,64 @@ static BOOL nsc_rle_decompress_data(NSC_CONTEXT* context) static BOOL nsc_stream_initialize(NSC_CONTEXT* context, wStream* s) { - int i; - - if (Stream_GetRemainingLength(s) < 20) + WINPR_ASSERT(context); + WINPR_ASSERT(context->priv); + if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20)) return FALSE; - for (i = 0; i < 4; i++) + size_t total = 0; + for (size_t i = 0; i < 4; i++) + { Stream_Read_UINT32(s, context->PlaneByteCount[i]); + total += context->PlaneByteCount[i]; + } Stream_Read_UINT8(s, context->ColorLossLevel); /* ColorLossLevel (1 byte) */ Stream_Read_UINT8(s, context->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */ Stream_Seek(s, 2); /* Reserved (2 bytes) */ context->Planes = Stream_Pointer(s); - return TRUE; + context->PlanesSize = total; + return Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, total); } static BOOL nsc_context_initialize(NSC_CONTEXT* context, wStream* s) { - int i; - UINT32 length; - UINT32 tempWidth; - UINT32 tempHeight; - if (!nsc_stream_initialize(context, s)) return FALSE; - length = context->width * context->height * 4; + const size_t blength = context->width * context->height * 4ull; if (!context->BitmapData) { - context->BitmapData = calloc(1, length + 16); + context->BitmapData = calloc(1, blength + 16); if (!context->BitmapData) return FALSE; - context->BitmapDataLength = length; + context->BitmapDataLength = blength; } - else if (length > context->BitmapDataLength) + else if (blength > context->BitmapDataLength) { void* tmp; - tmp = realloc(context->BitmapData, length + 16); + tmp = realloc(context->BitmapData, blength + 16); if (!tmp) return FALSE; context->BitmapData = tmp; - context->BitmapDataLength = length; + context->BitmapDataLength = blength; } - tempWidth = ROUND_UP_TO(context->width, 8); - tempHeight = ROUND_UP_TO(context->height, 2); + const UINT32 tempWidth = ROUND_UP_TO(context->width, 8); + const UINT32 tempHeight = ROUND_UP_TO(context->height, 2); /* The maximum length a decoded plane can reach in all cases */ - length = tempWidth * tempHeight; + const size_t plength = 1ull * tempWidth * tempHeight; - if (length > context->priv->PlaneBuffersLength) + if (plength > context->priv->PlaneBuffersLength) { - for (i = 0; i < 4; i++) + for (size_t i = 0; i < 4; i++) { - void* tmp = (BYTE*)realloc(context->priv->PlaneBuffers[i], length); + void* tmp = (BYTE*)realloc(context->priv->PlaneBuffers[i], plength); if (!tmp) return FALSE; @@ -284,13 +311,11 @@ static BOOL nsc_context_initialize(NSC_CONTEXT* context, wStream* s) context->priv->PlaneBuffers[i] = tmp; } - context->priv->PlaneBuffersLength = length; + context->priv->PlaneBuffersLength = plength; } - for (i = 0; i < 4; i++) - { + for (size_t i = 0; i < 4; i++) context->OrgByteCount[i] = context->width * context->height; - } if (context->ChromaSubsamplingLevel) { diff --git a/libfreerdp/codec/nsc_encode.c b/libfreerdp/codec/nsc_encode.c index fd9626a..477318c 100644 --- a/libfreerdp/codec/nsc_encode.c +++ b/libfreerdp/codec/nsc_encode.c @@ -119,6 +119,8 @@ static BOOL nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data, UI UINT16 rw; BYTE ccl; const BYTE* src; + const UINT32* src_32; + const UINT16* src_16; BYTE* yplane = NULL; BYTE* coplane = NULL; BYTE* cgplane = NULL; @@ -140,69 +142,85 @@ static BOOL nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data, UI coplane = context->priv->PlaneBuffers[1] + y * rw; cgplane = context->priv->PlaneBuffers[2] + y * rw; aplane = context->priv->PlaneBuffers[3] + y * context->width; + src_32 = (UINT32*)src; + src_16 = (UINT16*)src; for (x = 0; x < context->width; x++) { switch (context->format) { case PIXEL_FORMAT_BGRX32: - b_val = *src++; - g_val = *src++; - r_val = *src++; - src++; + b_val = (INT16)(*src_32 & 0xFF); + g_val = (INT16)((*src_32 >> 8) & 0xFF); + r_val = (INT16)((*src_32 >> 16) & 0xFF); a_val = 0xFF; + src_32++; break; case PIXEL_FORMAT_BGRA32: - b_val = *src++; - g_val = *src++; - r_val = *src++; - a_val = *src++; + b_val = (INT16)(*src_32 & 0xFF); + g_val = (INT16)((*src_32 >> 8) & 0xFF); + r_val = (INT16)((*src_32 >> 16) & 0xFF); + a_val = (INT16)((*src_32 >> 24) & 0xFF); + src_32++; break; case PIXEL_FORMAT_RGBX32: - r_val = *src++; - g_val = *src++; - b_val = *src++; - src++; + r_val = (INT16)(*src_32 & 0xFF); + g_val = (INT16)((*src_32 >> 8) & 0xFF); + b_val = (INT16)((*src_32 >> 16) & 0xFF); a_val = 0xFF; + src_32++; break; case PIXEL_FORMAT_RGBA32: - r_val = *src++; - g_val = *src++; - b_val = *src++; - a_val = *src++; + r_val = (INT16)(*src_32 & 0xFF); + g_val = (INT16)((*src_32 >> 8) & 0xFF); + b_val = (INT16)((*src_32 >> 16) & 0xFF); + a_val = (INT16)((*src_32 >> 24) & 0xFF); + src_32++; break; case PIXEL_FORMAT_BGR24: +#ifdef __LITTLE_ENDIAN__ b_val = *src++; g_val = *src++; r_val = *src++; +#else + r_val = *src++; + g_val = *src++; + b_val = *src++; +#endif a_val = 0xFF; break; case PIXEL_FORMAT_RGB24: +#ifdef __LITTLE_ENDIAN__ r_val = *src++; g_val = *src++; b_val = *src++; +#else + b_val = *src++; + g_val = *src++; + r_val = *src++; +#endif a_val = 0xFF; break; case PIXEL_FORMAT_BGR16: - b_val = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); - g_val = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); - r_val = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)); + b_val = (INT16)((*src_16) & 0x1F); + g_val = (INT16)((*src_16 >> 5) & 0x3F); + r_val = (INT16)((*src_16 >> 11) & 0x1F); a_val = 0xFF; - src += 2; + src_16++; break; case PIXEL_FORMAT_RGB16: - r_val = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); - g_val = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); - b_val = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)); + r_val = (INT16)((*src_16) & 0x1F); + g_val = (INT16)((*src_16 >> 5) & 0x3F); + b_val = (INT16)((*src_16 >> 11) & 0x1F); a_val = 0xFF; - src += 2; + src_16++; break; case PIXEL_FORMAT_A4: @@ -210,17 +228,17 @@ static BOOL nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, const BYTE* data, UI int shift; BYTE idx; shift = (7 - (x % 8)); - idx = ((*src) >> shift) & 1; - idx |= (((*(src + 1)) >> shift) & 1) << 1; - idx |= (((*(src + 2)) >> shift) & 1) << 2; - idx |= (((*(src + 3)) >> shift) & 1) << 3; + idx = (BYTE)(((*src_32 & 0xFF) >> shift) & 1); + idx |= (BYTE)(((((*src_32 >> 8) & 0xFF) >> shift) & 1) << 1); + idx |= (BYTE)(((((*src_32 >> 16) & 0xFF) >> shift) & 1) << 2); + idx |= (BYTE)(((((*src_32 >> 24) & 0xFF) >> shift) & 1) << 3); idx *= 3; r_val = (INT16)context->palette[idx]; g_val = (INT16)context->palette[idx + 1]; b_val = (INT16)context->palette[idx + 2]; if (shift == 0) - src += 4; + src_32++; } a_val = 0xFF; diff --git a/libfreerdp/codec/nsc_types.h b/libfreerdp/codec/nsc_types.h index 14c1a94..5a6506b 100644 --- a/libfreerdp/codec/nsc_types.h +++ b/libfreerdp/codec/nsc_types.h @@ -61,6 +61,7 @@ struct _NSC_CONTEXT UINT32 BitmapDataLength; BYTE* Planes; + size_t PlanesSize; UINT32 PlaneByteCount[4]; UINT32 ColorLossLevel; UINT32 ChromaSubsamplingLevel; diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index 12b9f6d..b4815a6 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -33,7 +33,8 @@ #define TAG FREERDP_TAG("codec") -#define ALIGN(val, align) ((val) % (align) == 0) ? (val) : ((val) + (align) - (val) % (align)) +#define PLANAR_ALIGN(val, align) \ + ((val) % (align) == 0) ? (val) : ((val) + (align) - (val) % (align)) static INLINE UINT32 planar_invert_format(BITMAP_PLANAR_CONTEXT* planar, BOOL alpha, UINT32 DstFormat) @@ -612,11 +613,20 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT const UINT32 h = MIN(nSrcHeight, nDstHeight); const primitives_t* prims = primitives_get(); + WINPR_ASSERT(planar); + WINPR_ASSERT(prims); + if (nDstStep <= 0) nDstStep = nDstWidth * GetBytesPerPixel(DstFormat); srcp = pSrcData; + if (!pSrcData) + { + WLog_ERR(TAG, "Invalid argument pSrcData=NULL"); + return FALSE; + } + if (!pDstData) { WLog_ERR(TAG, "Invalid argument pDstData=NULL"); @@ -1484,8 +1494,8 @@ BOOL freerdp_bitmap_planar_context_reset(BITMAP_PLANAR_CONTEXT* context, UINT32 return FALSE; context->bgr = FALSE; - context->maxWidth = ALIGN(width, 4); - context->maxHeight = ALIGN(height, 4); + context->maxWidth = PLANAR_ALIGN(width, 4); + context->maxHeight = PLANAR_ALIGN(height, 4); context->maxPlaneSize = context->maxWidth * context->maxHeight; context->nTempStep = context->maxWidth * 4; free(context->planesBuffer); diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index e95db2d..a05a334 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -415,7 +415,7 @@ static INLINE BOOL progressive_tile_allocate(RFX_PROGRESSIVE_TILE* tile) tile->stride = 4 * tile->width; { - size_t dataLen = tile->stride * tile->height * 1ULL; + size_t dataLen = 1ull * tile->stride * tile->height; tile->data = (BYTE*)_aligned_malloc(dataLen, 16); } @@ -2422,11 +2422,17 @@ INT32 progressive_decompress_ex(PROGRESSIVE_CONTEXT* progressive, const BYTE* pS for (j = 0; j < nbUpdateRects; j++) { const RECTANGLE_16* rect = &updateRects[j]; - const UINT32 nXSrc = rect->left - (nXDst + tile->x); - const UINT32 nYSrc = rect->top - (nYDst + tile->y); + if (rect->left < updateRect.left) + goto fail; + const UINT32 nXSrc = rect->left - updateRect.left; + const UINT32 nYSrc = rect->top - updateRect.top; const UINT32 width = rect->right - rect->left; const UINT32 height = rect->bottom - rect->top; + if (rect->left + width > surface->width) + goto fail; + if (rect->top + height > surface->height) + goto fail; if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, rect->left, rect->top, width, height, tile->data, progressive->format, tile->stride, nXSrc, nYSrc, NULL, FREERDP_FLIP_NONE)) diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index b41c157..ccbc5af 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -936,6 +936,27 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa Stream_Read_UINT8(&sub, tile->quantIdxY); /* quantIdxY (1 byte) */ Stream_Read_UINT8(&sub, tile->quantIdxCb); /* quantIdxCb (1 byte) */ Stream_Read_UINT8(&sub, tile->quantIdxCr); /* quantIdxCr (1 byte) */ + if (tile->quantIdxY >= context->numQuant) + { + WLog_Print(context->priv->log, WLOG_ERROR, "quantIdxY %" PRIu8 " >= numQuant %" PRIu8, + tile->quantIdxY, context->numQuant); + rc = FALSE; + break; + } + else if (tile->quantIdxCb >= context->numQuant) + { + WLog_Print(context->priv->log, WLOG_ERROR, "quantIdxCb %" PRIu8 " >= numQuant %" PRIu8, + tile->quantIdxCb, context->numQuant); + rc = FALSE; + break; + } + else if (tile->quantIdxCr >= context->numQuant) + { + WLog_Print(context->priv->log, WLOG_ERROR, "quantIdxCr %" PRIu8 " >= numQuant %" PRIu8, + tile->quantIdxCr, context->numQuant); + rc = FALSE; + break; + } Stream_Read_UINT16(&sub, tile->xIdx); /* xIdx (2 bytes) */ Stream_Read_UINT16(&sub, tile->yIdx); /* yIdx (2 bytes) */ Stream_Read_UINT16(&sub, tile->YLen); /* YLen (2 bytes) */ @@ -1109,8 +1130,18 @@ BOOL rfx_process_message(RFX_CONTEXT* context, const BYTE* data, UINT32 length, } } - Stream_StaticInit(&subStream, Stream_Pointer(s), blockLen - (6 + extraBlockLen)); - Stream_Seek(s, blockLen - (6 + extraBlockLen)); + const size_t blockLenNoHeader = blockLen - 6; + if (blockLenNoHeader < extraBlockLen) + { + WLog_Print(context->priv->log, WLOG_ERROR, + "blockLen too small(%" PRIu32 "), must be >= 6 + %" PRIu16, blockLen, + extraBlockLen); + return FALSE; + } + + const size_t subStreamLen = blockLenNoHeader - extraBlockLen; + Stream_StaticInit(&subStream, Stream_Pointer(s), subStreamLen); + Stream_Seek(s, subStreamLen); switch (blockType) { @@ -1231,6 +1262,11 @@ BOOL rfx_process_message(RFX_CONTEXT* context, const BYTE* data, UINT32 length, region16_uninit(&clippingRects); return TRUE; } + else + { + rfx_message_free(context, message); + context->currentMessage.freeArray = TRUE; + } WLog_ERR(TAG, "%s failed", __FUNCTION__); return FALSE; diff --git a/libfreerdp/codec/rfx_encode.c b/libfreerdp/codec/rfx_encode.c index b4f3936..355f743 100644 --- a/libfreerdp/codec/rfx_encode.c +++ b/libfreerdp/codec/rfx_encode.c @@ -49,6 +49,8 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i int x_exceed; int y_exceed; const BYTE* src; + const UINT32* src_32; + const UINT16* src_16; INT16 r, g, b; INT16 *r_last, *g_last, *b_last; x_exceed = 64 - width; @@ -57,6 +59,8 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i for (y = 0; y < height; y++) { src = rgb_data + y * rowstride; + src_32 = (UINT32*)src; + src_16 = (UINT16*)src; switch (pixel_format) { @@ -64,10 +68,10 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i case PIXEL_FORMAT_BGRA32: for (x = 0; x < width; x++) { - *b_buf++ = (INT16)(*src++); - *g_buf++ = (INT16)(*src++); - *r_buf++ = (INT16)(*src++); - src++; + *b_buf++ = (INT16)(*src_32 & 0xFF); + *g_buf++ = (INT16)((*src_32 >> 8) & 0xFF); + *r_buf++ = (INT16)((*src_32 >> 16) & 0xFF); + src_32++; } break; @@ -76,10 +80,10 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i case PIXEL_FORMAT_ABGR32: for (x = 0; x < width; x++) { - src++; - *b_buf++ = (INT16)(*src++); - *g_buf++ = (INT16)(*src++); - *r_buf++ = (INT16)(*src++); + *b_buf++ = (INT16)((*src_32 >> 8) & 0xFF); + *g_buf++ = (INT16)((*src_32 >> 16) & 0xFF); + *r_buf++ = (INT16)((*src_32 >> 24) & 0xFF); + src_32++; } break; @@ -88,10 +92,10 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i case PIXEL_FORMAT_RGBA32: for (x = 0; x < width; x++) { - *r_buf++ = (INT16)(*src++); - *g_buf++ = (INT16)(*src++); - *b_buf++ = (INT16)(*src++); - src++; + *r_buf++ = (INT16)(*src_32 & 0xFF); + *g_buf++ = (INT16)((*src_32 >> 8) & 0xFF); + *b_buf++ = (INT16)((*src_32 >> 16) & 0xFF); + src_32++; } break; @@ -100,10 +104,10 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i case PIXEL_FORMAT_ARGB32: for (x = 0; x < width; x++) { - src++; - *r_buf++ = (INT16)(*src++); - *g_buf++ = (INT16)(*src++); - *b_buf++ = (INT16)(*src++); + *r_buf++ = (INT16)((*src_32 >> 8) & 0xFF); + *g_buf++ = (INT16)((*src_32 >> 16) & 0xFF); + *b_buf++ = (INT16)((*src_32 >> 24) & 0xFF); + src_32++; } break; @@ -111,9 +115,15 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i case PIXEL_FORMAT_BGR24: for (x = 0; x < width; x++) { +#ifdef __LITTLE_ENDIAN__ *b_buf++ = (INT16)(*src++); *g_buf++ = (INT16)(*src++); *r_buf++ = (INT16)(*src++); +#else + *r_buf++ = (INT16)(*src++); + *g_buf++ = (INT16)(*src++); + *b_buf++ = (INT16)(*src++); +#endif } break; @@ -121,9 +131,15 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i case PIXEL_FORMAT_RGB24: for (x = 0; x < width; x++) { +#ifdef __LITTLE_ENDIAN__ *r_buf++ = (INT16)(*src++); *g_buf++ = (INT16)(*src++); *b_buf++ = (INT16)(*src++); +#else + *b_buf++ = (INT16)(*src++); + *g_buf++ = (INT16)(*src++); + *r_buf++ = (INT16)(*src++); +#endif } break; @@ -131,10 +147,10 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i case PIXEL_FORMAT_BGR16: for (x = 0; x < width; x++) { - *b_buf++ = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); - *g_buf++ = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); - *r_buf++ = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)); - src += 2; + *b_buf++ = (INT16)((*src_16) & 0x1F); + *g_buf++ = (INT16)((*src_16 >> 5) & 0x3F); + *r_buf++ = (INT16)((*src_16 >> 11) & 0x1F); + src_16++; } break; @@ -142,10 +158,10 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i case PIXEL_FORMAT_RGB16: for (x = 0; x < width; x++) { - *r_buf++ = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); - *g_buf++ = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); - *b_buf++ = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)); - src += 2; + *r_buf++ = (INT16)((*src_16 & 0x1F)); + *g_buf++ = (INT16)((*src_16 >> 5) & 0x3F); + *b_buf++ = (INT16)((*src_16 >> 11) & 0x1F); + src_16++; } break; @@ -159,17 +175,17 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i int shift; BYTE idx; shift = (7 - (x % 8)); - idx = ((*src) >> shift) & 1; - idx |= (((*(src + 1)) >> shift) & 1) << 1; - idx |= (((*(src + 2)) >> shift) & 1) << 2; - idx |= (((*(src + 3)) >> shift) & 1) << 3; + idx = (BYTE)(((*src_32 & 0xFF) >> shift) & 1); + idx |= (BYTE)(((((*src_32 >> 8) & 0xFF) >> shift) & 1) << 1); + idx |= (BYTE)(((((*src_32 >> 16) & 0xFF) >> shift) & 1) << 2); + idx |= (BYTE)(((((*src_32 >> 24) & 0xFF) >> shift) & 1) << 3); idx *= 3; *r_buf++ = (INT16)palette[idx]; *g_buf++ = (INT16)palette[idx + 1]; *b_buf++ = (INT16)palette[idx + 2]; if (shift == 0) - src += 4; + src_32++; } break; diff --git a/libfreerdp/codec/xcrush.c b/libfreerdp/codec/xcrush.c index 350801d..56bf649 100644 --- a/libfreerdp/codec/xcrush.c +++ b/libfreerdp/codec/xcrush.c @@ -674,7 +674,7 @@ static int xcrush_generate_output(XCRUSH_CONTEXT* xcrush, BYTE* OutputBuffer, UI if (&OutputBuffer[2] >= &OutputBuffer[OutputSize]) return -6001; /* error */ - *((UINT16*)OutputBuffer) = MatchCount; + Data_Write_UINT16(OutputBuffer, MatchCount); MatchDetails = (RDP61_MATCH_DETAILS*)&OutputBuffer[2]; Literals = (BYTE*)&MatchDetails[MatchCount]; @@ -683,12 +683,12 @@ static int xcrush_generate_output(XCRUSH_CONTEXT* xcrush, BYTE* OutputBuffer, UI for (MatchIndex = 0; MatchIndex < MatchCount; MatchIndex++) { - MatchDetails[MatchIndex].MatchLength = - (UINT16)(xcrush->OptimizedMatches[MatchIndex].MatchLength); - MatchDetails[MatchIndex].MatchOutputOffset = - (UINT16)(xcrush->OptimizedMatches[MatchIndex].MatchOffset - HistoryOffset); - MatchDetails[MatchIndex].MatchHistoryOffset = - xcrush->OptimizedMatches[MatchIndex].ChunkOffset; + Data_Write_UINT16(&MatchDetails[MatchIndex].MatchLength, + xcrush->OptimizedMatches[MatchIndex].MatchLength); + Data_Write_UINT16(&MatchDetails[MatchIndex].MatchOutputOffset, + xcrush->OptimizedMatches[MatchIndex].MatchOffset - HistoryOffset); + Data_Write_UINT32(&MatchDetails[MatchIndex].MatchHistoryOffset, + xcrush->OptimizedMatches[MatchIndex].ChunkOffset); } CurrentOffset = HistoryOffset; diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c index e260aa6..841b508 100644 --- a/libfreerdp/codec/zgfx.c +++ b/libfreerdp/codec/zgfx.c @@ -259,7 +259,11 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t zgfx->pbInputCurrent = pbSegment; zgfx->pbInputEnd = &pbSegment[cbSegment - 1]; /* NumberOfBitsToDecode = ((NumberOfBytesToDecode - 1) * 8) - ValueOfLastByte */ - zgfx->cBitsRemaining = 8 * (cbSegment - 1) - *zgfx->pbInputEnd; + const UINT32 bits = 8u * (cbSegment - 1u); + if (bits < *zgfx->pbInputEnd) + return FALSE; + + zgfx->cBitsRemaining = bits - *zgfx->pbInputEnd; zgfx->cBitsCurrent = 0; zgfx->BitsCurrent = 0; diff --git a/libfreerdp/common/settings_getters.c b/libfreerdp/common/settings_getters.c index 76f6646..8df8957 100644 --- a/libfreerdp/common/settings_getters.c +++ b/libfreerdp/common/settings_getters.c @@ -231,6 +231,9 @@ BOOL freerdp_settings_get_bool(const rdpSettings* settings, size_t id) case FreeRDP_GrabKeyboard: return settings->GrabKeyboard; + case FreeRDP_GrabMouse: + return settings->GrabMouse; + case FreeRDP_HasExtendedMouseEvent: return settings->HasExtendedMouseEvent; @@ -809,6 +812,10 @@ BOOL freerdp_settings_set_bool(rdpSettings* settings, size_t id, BOOL val) settings->GrabKeyboard = val; break; + case FreeRDP_GrabMouse: + settings->GrabMouse = val; + break; + case FreeRDP_HasExtendedMouseEvent: settings->HasExtendedMouseEvent = val; break; diff --git a/libfreerdp/common/settings_str.c b/libfreerdp/common/settings_str.c index d4e20ae..6fa11c0 100644 --- a/libfreerdp/common/settings_str.c +++ b/libfreerdp/common/settings_str.c @@ -87,6 +87,7 @@ static const struct settings_str_entry settings_map[] = { { FreeRDP_GfxSmallCache, 0, "FreeRDP_GfxSmallCache" }, { FreeRDP_GfxThinClient, 0, "FreeRDP_GfxThinClient" }, { FreeRDP_GrabKeyboard, 0, "FreeRDP_GrabKeyboard" }, + { FreeRDP_GrabMouse, 0, "FreeRDP_GrabMouse" }, { FreeRDP_HasExtendedMouseEvent, 0, "FreeRDP_HasExtendedMouseEvent" }, { FreeRDP_HasHorizontalWheel, 0, "FreeRDP_HasHorizontalWheel" }, { FreeRDP_HasMonitorAttributes, 0, "FreeRDP_HasMonitorAttributes" }, diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 34ccbb7..0f19914 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -1373,12 +1374,13 @@ static BOOL update_read_draw_nine_grid_order(wStream* s, const ORDER_INFO* order static BOOL update_read_multi_dstblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_DSTBLT_ORDER* multi_dstblt) { + UINT32 numRectangles = 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)) + !read_order_field_byte(orderInfo, s, 6, &numRectangles, TRUE)) return FALSE; if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) @@ -1386,12 +1388,21 @@ static BOOL update_read_multi_dstblt_order(wStream* s, const ORDER_INFO* orderIn if (Stream_GetRemainingLength(s) < 2) return FALSE; + multi_dstblt->numRectangles = numRectangles; Stream_Read_UINT16(s, multi_dstblt->cbData); return update_read_delta_rects(s, multi_dstblt->rectangles, &multi_dstblt->numRectangles); } - + if (numRectangles > multi_dstblt->numRectangles) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, + multi_dstblt->numRectangles); + return FALSE; + } + multi_dstblt->numRectangles = numRectangles; return TRUE; } + static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_PATBLT_ORDER* multi_patblt) { @@ -1407,7 +1418,8 @@ static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderIn if (!update_read_brush(s, &multi_patblt->brush, orderInfo->fieldFlags >> 7)) return FALSE; - if (!read_order_field_byte(orderInfo, s, 13, &multi_patblt->numRectangles, TRUE)) + UINT32 numRectangles = multi_patblt->numRectangles; + if (!read_order_field_byte(orderInfo, s, 13, &numRectangles, TRUE)) return FALSE; if ((orderInfo->fieldFlags & ORDER_FIELD_14) != 0) @@ -1415,17 +1427,31 @@ static BOOL update_read_multi_patblt_order(wStream* s, const ORDER_INFO* orderIn if (Stream_GetRemainingLength(s) < 2) return FALSE; + multi_patblt->numRectangles = numRectangles; Stream_Read_UINT16(s, multi_patblt->cbData); if (!update_read_delta_rects(s, multi_patblt->rectangles, &multi_patblt->numRectangles)) return FALSE; } + if (numRectangles > multi_patblt->numRectangles) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, + multi_patblt->numRectangles); + return FALSE; + } + multi_patblt->numRectangles = numRectangles; + return TRUE; } static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_SCRBLT_ORDER* multi_scrblt) { + WINPR_ASSERT(orderInfo); + WINPR_ASSERT(multi_scrblt); + + UINT32 numRectangles = 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) || @@ -1433,7 +1459,7 @@ static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderIn !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)) + !read_order_field_byte(orderInfo, s, 8, &numRectangles, TRUE)) return FALSE; if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0) @@ -1441,10 +1467,20 @@ static BOOL update_read_multi_scrblt_order(wStream* s, const ORDER_INFO* orderIn if (Stream_GetRemainingLength(s) < 2) return FALSE; + multi_scrblt->numRectangles = numRectangles; Stream_Read_UINT16(s, multi_scrblt->cbData); return update_read_delta_rects(s, multi_scrblt->rectangles, &multi_scrblt->numRectangles); } + if (numRectangles > multi_scrblt->numRectangles) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, + multi_scrblt->numRectangles); + return FALSE; + } + multi_scrblt->numRectangles = numRectangles; + return TRUE; } static BOOL update_read_multi_opaque_rect_order(wStream* s, const ORDER_INFO* orderInfo, @@ -1484,7 +1520,8 @@ static BOOL update_read_multi_opaque_rect_order(wStream* s, const ORDER_INFO* or multi_opaque_rect->color = (multi_opaque_rect->color & 0x0000FFFF) | ((UINT32)byte << 16); } - if (!read_order_field_byte(orderInfo, s, 8, &multi_opaque_rect->numRectangles, TRUE)) + UINT32 numRectangles = multi_opaque_rect->numRectangles; + if (!read_order_field_byte(orderInfo, s, 8, &numRectangles, TRUE)) return FALSE; if ((orderInfo->fieldFlags & ORDER_FIELD_09) != 0) @@ -1492,22 +1529,32 @@ static BOOL update_read_multi_opaque_rect_order(wStream* s, const ORDER_INFO* or if (Stream_GetRemainingLength(s) < 2) return FALSE; + multi_opaque_rect->numRectangles = numRectangles; Stream_Read_UINT16(s, multi_opaque_rect->cbData); return update_read_delta_rects(s, multi_opaque_rect->rectangles, &multi_opaque_rect->numRectangles); } + if (numRectangles > multi_opaque_rect->numRectangles) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numRectangles %" PRIu32 " > %" PRIu32, orderName, numRectangles, + multi_opaque_rect->numRectangles); + return FALSE; + } + multi_opaque_rect->numRectangles = numRectangles; return TRUE; } static BOOL update_read_multi_draw_nine_grid_order(wStream* s, const ORDER_INFO* orderInfo, MULTI_DRAW_NINE_GRID_ORDER* multi_draw_nine_grid) { + UINT32 nDeltaEntries = 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)) + !read_order_field_byte(orderInfo, s, 6, &nDeltaEntries, TRUE)) return FALSE; if ((orderInfo->fieldFlags & ORDER_FIELD_07) != 0) @@ -1515,11 +1562,21 @@ static BOOL update_read_multi_draw_nine_grid_order(wStream* s, const ORDER_INFO* if (Stream_GetRemainingLength(s) < 2) return FALSE; + multi_draw_nine_grid->nDeltaEntries = nDeltaEntries; Stream_Read_UINT16(s, multi_draw_nine_grid->cbData); return update_read_delta_rects(s, multi_draw_nine_grid->rectangles, &multi_draw_nine_grid->nDeltaEntries); } + if (nDeltaEntries > multi_draw_nine_grid->nDeltaEntries) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s nDeltaEntries %" PRIu32 " > %" PRIu32, orderName, nDeltaEntries, + multi_draw_nine_grid->nDeltaEntries); + return FALSE; + } + multi_draw_nine_grid->nDeltaEntries = nDeltaEntries; + return TRUE; } static BOOL update_read_line_to_order(wStream* s, const ORDER_INFO* orderInfo, @@ -1610,6 +1667,14 @@ static BOOL update_read_polyline_order(wStream* s, const ORDER_INFO* orderInfo, return update_read_delta_points(s, polyline->points, polyline->numDeltaEntries, polyline->xStart, polyline->yStart); } + if (new_num > polyline->numDeltaEntries) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numDeltaEntries %" PRIu32 " > %" PRIu32, orderName, new_num, + polyline->numDeltaEntries); + return FALSE; + } + polyline->numDeltaEntries = new_num; return TRUE; } @@ -1942,6 +2007,13 @@ static BOOL update_read_polygon_sc_order(wStream* s, const ORDER_INFO* orderInfo return update_read_delta_points(s, polygon_sc->points, polygon_sc->numPoints, polygon_sc->xStart, polygon_sc->yStart); } + if (num > polygon_sc->numPoints) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numPoints %" PRIu32 " > %" PRIu32, orderName, num, polygon_sc->numPoints); + return FALSE; + } + polygon_sc->numPoints = num; return TRUE; } @@ -1987,6 +2059,14 @@ static BOOL update_read_polygon_cb_order(wStream* s, const ORDER_INFO* orderInfo return FALSE; } + if (num > polygon_cb->numPoints) + { + const char* orderName = __func__; + WLog_ERR(TAG, "%s numPoints %" PRIu32 " > %" PRIu32, orderName, num, polygon_cb->numPoints); + return FALSE; + } + polygon_cb->numPoints = num; + polygon_cb->backMode = (polygon_cb->bRop2 & 0x80) ? BACKMODE_TRANSPARENT : BACKMODE_OPAQUE; polygon_cb->bRop2 = (polygon_cb->bRop2 & 0x1F); return TRUE; diff --git a/libfreerdp/core/server.c b/libfreerdp/core/server.c index a786cbd..b8298a2 100644 --- a/libfreerdp/core/server.c +++ b/libfreerdp/core/server.c @@ -493,7 +493,7 @@ BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer) { ULONG written; vcm->drdynvc_channel = channel; - dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */ + Data_Write_UINT32(&dynvc_caps, 0x00010050); /* DYNVC_CAPS_VERSION1 (4 bytes) */ if (!WTSVirtualChannelWrite(channel, (PCHAR)&dynvc_caps, sizeof(dynvc_caps), &written)) return FALSE; diff --git a/libfreerdp/core/test/settings_property_lists.h b/libfreerdp/core/test/settings_property_lists.h index 69f7bce..a85c2ff 100644 --- a/libfreerdp/core/test/settings_property_lists.h +++ b/libfreerdp/core/test/settings_property_lists.h @@ -76,6 +76,7 @@ static const size_t bool_list_indices[] = { FreeRDP_GfxSmallCache, FreeRDP_GfxThinClient, FreeRDP_GrabKeyboard, + FreeRDP_GrabMouse, FreeRDP_HasExtendedMouseEvent, FreeRDP_HasHorizontalWheel, FreeRDP_HasMonitorAttributes, diff --git a/libfreerdp/core/window.c b/libfreerdp/core/window.c index 51411c8..cb0acb9 100644 --- a/libfreerdp/core/window.c +++ b/libfreerdp/core/window.c @@ -359,33 +359,31 @@ static BOOL update_read_window_state_order(wStream* s, WINDOW_ORDER_INFO* orderI Stream_Read_UINT16(s, windowState->numWindowRects); /* numWindowRects (2 bytes) */ - if (windowState->numWindowRects == 0) + if (windowState->numWindowRects > 0) { - return TRUE; - } + size = sizeof(RECTANGLE_16) * windowState->numWindowRects; + newRect = (RECTANGLE_16*)realloc(windowState->windowRects, size); - size = sizeof(RECTANGLE_16) * windowState->numWindowRects; - newRect = (RECTANGLE_16*)realloc(windowState->windowRects, size); + if (!newRect) + { + free(windowState->windowRects); + windowState->windowRects = NULL; + return FALSE; + } - if (!newRect) - { - free(windowState->windowRects); - windowState->windowRects = NULL; - return FALSE; - } + windowState->windowRects = newRect; - windowState->windowRects = newRect; + if (Stream_GetRemainingLength(s) < 8 * windowState->numWindowRects) + return FALSE; - if (Stream_GetRemainingLength(s) < 8 * windowState->numWindowRects) - return FALSE; - - /* windowRects */ - for (i = 0; i < windowState->numWindowRects; i++) - { - Stream_Read_UINT16(s, windowState->windowRects[i].left); /* left (2 bytes) */ - Stream_Read_UINT16(s, windowState->windowRects[i].top); /* top (2 bytes) */ - Stream_Read_UINT16(s, windowState->windowRects[i].right); /* right (2 bytes) */ - Stream_Read_UINT16(s, windowState->windowRects[i].bottom); /* bottom (2 bytes) */ + /* windowRects */ + for (i = 0; i < windowState->numWindowRects; i++) + { + Stream_Read_UINT16(s, windowState->windowRects[i].left); /* left (2 bytes) */ + Stream_Read_UINT16(s, windowState->windowRects[i].top); /* top (2 bytes) */ + Stream_Read_UINT16(s, windowState->windowRects[i].right); /* right (2 bytes) */ + Stream_Read_UINT16(s, windowState->windowRects[i].bottom); /* bottom (2 bytes) */ + } } } diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index 943b4df..f08a4b8 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -950,10 +950,12 @@ WINPR_MD_TYPE crypto_cert_get_signature_alg(X509* xcert) { WINPR_ASSERT(xcert); - const int nid = X509_get_signature_nid(xcert); + EVP_PKEY* evp = X509_get0_pubkey(xcert); + WINPR_ASSERT(evp); int hash_nid = 0; - if (OBJ_find_sigid_algs(nid, &hash_nid, NULL) != 1) + const int res = EVP_PKEY_get_default_digest_nid(evp, &hash_nid); + if (res <= 0) return WINPR_MD_NONE; switch (hash_nid) @@ -976,7 +978,7 @@ WINPR_MD_TYPE crypto_cert_get_signature_alg(X509* xcert) return WINPR_MD_SHA512; case NID_ripemd160: return WINPR_MD_RIPEMD160; -#if (OPENSSL_VERSION_NUMBER >= 0x1010101fL) || defined(LIBRESSL_VERSION_NUMBER) +#if (OPENSSL_VERSION_NUMBER >= 0x1010101fL) && !defined(LIBRESSL_VERSION_NUMBER) case NID_sha3_224: return WINPR_MD_SHA3_224; case NID_sha3_256: @@ -985,11 +987,11 @@ WINPR_MD_TYPE crypto_cert_get_signature_alg(X509* xcert) return WINPR_MD_SHA3_384; case NID_sha3_512: return WINPR_MD_SHA3_512; -#endif case NID_shake128: return WINPR_MD_SHAKE128; case NID_shake256: return WINPR_MD_SHAKE256; +#endif case NID_undef: default: return WINPR_MD_NONE; diff --git a/libfreerdp/gdi/bitmap.c b/libfreerdp/gdi/bitmap.c index 8fde465..cac8158 100644 --- a/libfreerdp/gdi/bitmap.c +++ b/libfreerdp/gdi/bitmap.c @@ -148,7 +148,7 @@ HGDI_BITMAP gdi_CreateCompatibleBitmap(HGDI_DC hdc, UINT32 nWidth, UINT32 nHeigh hBitmap->width = nWidth; hBitmap->height = nHeight; hBitmap->data = - _aligned_malloc(nWidth * nHeight * GetBytesPerPixel(hBitmap->format) * 1ULL, 16); + _aligned_malloc(1ull * nWidth * nHeight * GetBytesPerPixel(hBitmap->format), 16); hBitmap->free = _aligned_free; if (!hBitmap->data) diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 5ca905b..37a0104 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -997,16 +997,46 @@ static BOOL gdi_surface_frame_marker(rdpContext* context, return TRUE; } +static BOOL intersect_rect(const rdpGdi* gdi, const SURFACE_BITS_COMMAND* cmd, RECTANGLE_16* prect) +{ + const UINT32 w = (const UINT32)gdi->width; + const UINT32 h = (const UINT32)gdi->height; + + if (cmd->destLeft > w) + return FALSE; + if (cmd->destRight > w) + return FALSE; + if (cmd->destLeft > cmd->destRight) + return FALSE; + if (cmd->destRight > UINT16_MAX) + return FALSE; + + if (cmd->destTop > h) + return FALSE; + if (cmd->destBottom > h) + return FALSE; + if (cmd->destTop > cmd->destBottom) + return FALSE; + if (cmd->destBottom > UINT16_MAX) + return FALSE; + + prect->left = (const UINT16)cmd->destLeft; + prect->top = (const UINT16)cmd->destTop; + prect->right = MIN((UINT16)cmd->destRight, prect->left + cmd->bmp.width); + prect->bottom = MIN((UINT16)cmd->destBottom, prect->top + cmd->bmp.height); + return TRUE; +} + static BOOL gdi_surface_bits(rdpContext* context, const SURFACE_BITS_COMMAND* cmd) { BOOL result = FALSE; DWORD format; - rdpGdi* gdi; + rdpGdi* gdi = NULL; size_t size; REGION16 region; - RECTANGLE_16 cmdRect; - UINT32 i, nbRects; - const RECTANGLE_16* rects; + RECTANGLE_16 cmdRect = { 0 }; + UINT32 nbRects; + const RECTANGLE_16* rects = NULL; if (!context || !cmd) return FALSE; @@ -1020,16 +1050,15 @@ static BOOL gdi_surface_bits(rdpContext* context, const SURFACE_BITS_COMMAND* cm cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom, cmd->bmp.bpp, cmd->bmp.flags, cmd->bmp.codecID, cmd->bmp.width, cmd->bmp.height, cmd->bmp.bitmapDataLength); region16_init(®ion); - cmdRect.left = cmd->destLeft; - cmdRect.top = cmd->destTop; - cmdRect.right = cmdRect.left + cmd->bmp.width; - cmdRect.bottom = cmdRect.top + cmd->bmp.height; + + if (!intersect_rect(gdi, cmd, &cmdRect)) + goto out; switch (cmd->bmp.codecID) { case RDP_CODEC_ID_REMOTEFX: if (!rfx_process_message(context->codecs->rfx, cmd->bmp.bitmapData, - cmd->bmp.bitmapDataLength, cmd->destLeft, cmd->destTop, + cmd->bmp.bitmapDataLength, cmdRect.left, cmdRect.top, gdi->primary_buffer, gdi->dstFormat, gdi->stride, gdi->height, ®ion)) { @@ -1042,11 +1071,11 @@ static BOOL gdi_surface_bits(rdpContext* context, const SURFACE_BITS_COMMAND* cm case RDP_CODEC_ID_NSCODEC: format = gdi->dstFormat; - if (!nsc_process_message(context->codecs->nsc, cmd->bmp.bpp, cmd->bmp.width, - cmd->bmp.height, cmd->bmp.bitmapData, - cmd->bmp.bitmapDataLength, gdi->primary_buffer, format, - gdi->stride, cmd->destLeft, cmd->destTop, cmd->bmp.width, - cmd->bmp.height, FREERDP_FLIP_VERTICAL)) + if (!nsc_process_message( + context->codecs->nsc, cmd->bmp.bpp, cmd->bmp.width, cmd->bmp.height, + cmd->bmp.bitmapData, cmd->bmp.bitmapDataLength, gdi->primary_buffer, format, + gdi->stride, cmdRect.left, cmdRect.top, cmdRect.right - cmdRect.left, + cmdRect.bottom - cmdRect.top, FREERDP_FLIP_VERTICAL)) { WLog_ERR(TAG, "Failed to process NSCodec message"); goto out; @@ -1057,17 +1086,18 @@ static BOOL gdi_surface_bits(rdpContext* context, const SURFACE_BITS_COMMAND* cm case RDP_CODEC_ID_NONE: format = gdi_get_pixel_format(cmd->bmp.bpp); - size = cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format) * 1ULL; + size = 1ull * cmd->bmp.width * cmd->bmp.height * GetBytesPerPixel(format); if (size > cmd->bmp.bitmapDataLength) { WLog_ERR(TAG, "Short nocodec message: got %" PRIu32 " bytes, require %" PRIuz, cmd->bmp.bitmapDataLength, size); goto out; } - if (!freerdp_image_copy(gdi->primary_buffer, gdi->dstFormat, gdi->stride, cmd->destLeft, - cmd->destTop, cmd->bmp.width, cmd->bmp.height, - cmd->bmp.bitmapData, format, 0, 0, 0, &gdi->palette, - FREERDP_FLIP_VERTICAL)) + + if (!freerdp_image_copy(gdi->primary_buffer, gdi->dstFormat, gdi->stride, cmdRect.left, + cmdRect.top, cmdRect.right - cmdRect.left, + cmdRect.bottom - cmdRect.top, cmd->bmp.bitmapData, format, 0, 0, + 0, &gdi->palette, FREERDP_FLIP_VERTICAL)) { WLog_ERR(TAG, "Failed to process nocodec message"); goto out; @@ -1084,7 +1114,7 @@ static BOOL gdi_surface_bits(rdpContext* context, const SURFACE_BITS_COMMAND* cm if (!(rects = region16_rects(®ion, &nbRects))) goto out; - for (i = 0; i < nbRects; i++) + for (UINT32 i = 0; i < nbRects; i++) { UINT32 left = rects[i].left; UINT32 top = rects[i].top; diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c index a3b7505..3970715 100644 --- a/libfreerdp/gdi/gfx.c +++ b/libfreerdp/gdi/gfx.c @@ -726,7 +726,7 @@ static UINT gdi_SurfaceCommand_Alpha(rdpGdi* gdi, RdpgfxClientContext* context, { UINT32 x, y; - if (Stream_GetRemainingLength(&s) < cmd->height * cmd->width * 1ULL) + if (Stream_GetRemainingLength(&s) < 1ull * cmd->height * cmd->width) return ERROR_INVALID_DATA; for (y = cmd->top; y < cmd->top + cmd->height; y++) @@ -1025,7 +1025,7 @@ static UINT gdi_CreateSurface(RdpgfxClientContext* context, } surface->scanline = gfx_align_scanline(surface->width * 4UL, 16); - surface->data = (BYTE*)_aligned_malloc(surface->scanline * surface->height * 1ULL, 16); + surface->data = (BYTE*)_aligned_malloc(1ull * surface->scanline * surface->height, 16); if (!surface->data) { @@ -1079,6 +1079,28 @@ static UINT gdi_DeleteSurface(RdpgfxClientContext* context, return rc; } +static BOOL intersect_rect(const RECTANGLE_16* rect, const gdiGfxSurface* surface, + RECTANGLE_16* prect) +{ + WINPR_ASSERT(rect); + WINPR_ASSERT(surface); + WINPR_ASSERT(prect); + + if (rect->left > rect->right) + return FALSE; + if (rect->left > surface->width) + return FALSE; + if (rect->top > rect->bottom) + return FALSE; + if (rect->top > surface->height) + return FALSE; + prect->left = rect->left; + prect->top = rect->top; + prect->right = MIN(rect->right, surface->width); + prect->bottom = MIN(rect->bottom, surface->height); + return TRUE; +} + /** * Function description * @@ -1087,40 +1109,36 @@ static UINT gdi_DeleteSurface(RdpgfxClientContext* context, static UINT gdi_SolidFill(RdpgfxClientContext* context, const RDPGFX_SOLID_FILL_PDU* solidFill) { UINT status = ERROR_INTERNAL_ERROR; - UINT16 index; - UINT32 color; - BYTE a, r, g, b; - UINT32 nWidth, nHeight; - RECTANGLE_16* rect; - gdiGfxSurface* surface; - RECTANGLE_16 invalidRect; + BYTE a = 0; + RECTANGLE_16 invalidRect = { 0 }; rdpGdi* gdi = (rdpGdi*)context->custom; + EnterCriticalSection(&context->mux); - surface = (gdiGfxSurface*)context->GetSurfaceData(context, solidFill->surfaceId); + + WINPR_ASSERT(context->GetSurfaceData); + gdiGfxSurface* surface = (gdiGfxSurface*)context->GetSurfaceData(context, solidFill->surfaceId); if (!surface) goto fail; - b = solidFill->fillPixel.B; - g = solidFill->fillPixel.G; - r = solidFill->fillPixel.R; - /* a = solidFill->fillPixel.XA; - * Ignore alpha channel, this is a solid fill. */ + const BYTE b = solidFill->fillPixel.B; + const BYTE g = solidFill->fillPixel.G; + const BYTE r = solidFill->fillPixel.R; a = 0xFF; - color = FreeRDPGetColor(surface->format, r, g, b, a); + const UINT32 color = FreeRDPGetColor(surface->format, r, g, b, a); - for (index = 0; index < solidFill->fillRectCount; index++) + for (UINT16 index = 0; index < solidFill->fillRectCount; index++) { - rect = &(solidFill->fillRects[index]); - nWidth = rect->right - rect->left; - nHeight = rect->bottom - rect->top; - invalidRect.left = rect->left; - invalidRect.top = rect->top; - invalidRect.right = rect->right; - invalidRect.bottom = rect->bottom; + const RECTANGLE_16* rect = &(solidFill->fillRects[index]); - if (!freerdp_image_fill(surface->data, surface->format, surface->scanline, rect->left, - rect->top, nWidth, nHeight, color)) + if (!intersect_rect(rect, surface, &invalidRect)) + goto fail; + + const UINT32 nWidth = invalidRect.right - invalidRect.left; + const UINT32 nHeight = invalidRect.bottom - invalidRect.top; + + if (!freerdp_image_fill(surface->data, surface->format, surface->scanline, invalidRect.left, + invalidRect.top, nWidth, nHeight, color)) goto fail; region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect); diff --git a/libfreerdp/gdi/graphics.c b/libfreerdp/gdi/graphics.c index c8b5fc9..479eac9 100644 --- a/libfreerdp/gdi/graphics.c +++ b/libfreerdp/gdi/graphics.c @@ -52,7 +52,7 @@ HGDI_BITMAP gdi_create_bitmap(rdpGdi* gdi, UINT32 nWidth, UINT32 nHeight, UINT32 return NULL; nDstStep = nWidth * GetBytesPerPixel(gdi->dstFormat); - pDstData = _aligned_malloc(nHeight * nDstStep * 1ULL, 16); + pDstData = _aligned_malloc(1ull * nHeight * nDstStep, 16); if (!pDstData) return NULL; diff --git a/libfreerdp/gdi/shape.c b/libfreerdp/gdi/shape.c index 6c45e0c..51a8a36 100644 --- a/libfreerdp/gdi/shape.c +++ b/libfreerdp/gdi/shape.c @@ -158,7 +158,7 @@ BOOL gdi_FillRect(HGDI_DC hdc, const HGDI_RECT rect, HGDI_BRUSH hbr) for (y = 1; y < nHeight; y++) { BYTE* dstp = gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y); - memcpy(dstp, srcp, nWidth * formatSize * 1ULL); + memcpy(dstp, srcp, 1ull * nWidth * formatSize); } break; diff --git a/libfreerdp/gdi/video.c b/libfreerdp/gdi/video.c index 0e12c52..8c74f0a 100644 --- a/libfreerdp/gdi/video.c +++ b/libfreerdp/gdi/video.c @@ -66,7 +66,7 @@ static VideoSurface* gdiVideoCreateSurface(VideoClientContext* video, BYTE* data ret->base.w = width; ret->base.h = height; ret->scanline = width * bpp; - ret->image = _aligned_malloc(ret->scanline * height * 1ULL, 16); + ret->image = _aligned_malloc(1ull * ret->scanline * height, 16); if (!ret->image) { diff --git a/libfreerdp/primitives/prim_copy.c b/libfreerdp/primitives/prim_copy.c index ae841d0..30c9cb1 100644 --- a/libfreerdp/primitives/prim_copy.c +++ b/libfreerdp/primitives/prim_copy.c @@ -60,14 +60,14 @@ static BOOL memory_regions_overlap_2d(const BYTE* p1, int p1Step, int p1Size, co if (p1m <= p2m) { - ULONG_PTR p1mEnd = p1m + (height - 1) * p1Step * 1ULL + width * p1Size * 1ULL; + ULONG_PTR p1mEnd = p1m + 1ull * (height - 1) * p1Step + 1ull * width * p1Size; if (p1mEnd > p2m) return TRUE; } else { - ULONG_PTR p2mEnd = p2m + (height - 1) * p2Step * 1ULL + width * p2Size * 1ULL; + ULONG_PTR p2mEnd = p2m + 1ull * (height - 1) * p2Step + 1ull * width * p2Size; if (p2mEnd > p1m) return TRUE; diff --git a/libfreerdp/primitives/primitives.c b/libfreerdp/primitives/primitives.c index 0a4303d..6820a58 100644 --- a/libfreerdp/primitives/primitives.c +++ b/libfreerdp/primitives/primitives.c @@ -157,7 +157,7 @@ static primitives_YUV_benchmark* primitives_YUV_benchmark_init(primitives_YUV_be if (!buf) goto fail; - winpr_RAND(buf, roi->width * roi->height * 1ULL); + winpr_RAND(buf, 1ull * roi->width * roi->height); ret->steps[i] = roi->width; } diff --git a/uwac/CMakeLists.txt b/uwac/CMakeLists.txt index eaee928..c97cd4f 100644 --- a/uwac/CMakeLists.txt +++ b/uwac/CMakeLists.txt @@ -17,8 +17,8 @@ # Soname versioning set(UWAC_VERSION_MAJOR "0") -set(UWAC_VERSION_MINOR "1") -set(UWAC_VERSION_REVISION "1") +set(UWAC_VERSION_MINOR "2") +set(UWAC_VERSION_REVISION "0") set(UWAC_VERSION "${UWAC_VERSION_MAJOR}.${UWAC_VERSION_MINOR}.${UWAC_VERSION_REVISION}") set(UWAC_VERSION_FULL "${UWAC_VERSION}") set(UWAC_API_VERSION "${UWAC_VERSION_MAJOR}") diff --git a/uwac/include/uwac/uwac.h b/uwac/include/uwac/uwac.h index c3ad12c..a86b48b 100644 --- a/uwac/include/uwac/uwac.h +++ b/uwac/include/uwac/uwac.h @@ -107,7 +107,9 @@ enum UWAC_EVENT_CLIPBOARD_OFFER, UWAC_EVENT_OUTPUT_GEOMETRY, UWAC_EVENT_KEYBOARD_MODIFIERS, - UWAC_EVENT_POINTER_AXIS_DISCRETE + UWAC_EVENT_POINTER_AXIS_DISCRETE, + UWAC_EVENT_POINTER_FRAME, + UWAC_EVENT_POINTER_SOURCE }; /** @brief window states */ @@ -195,6 +197,23 @@ struct uwac_pointer_axis_event }; typedef struct uwac_pointer_axis_event UwacPointerAxisEvent; +struct uwac_pointer_frame_event +{ + int type; + UwacWindow* window; + UwacSeat* seat; +}; +typedef struct uwac_pointer_frame_event UwacPointerFrameEvent; + +struct uwac_pointer_source_event +{ + int type; + UwacWindow* window; + UwacSeat* seat; + enum wl_pointer_axis_source axis_source; +}; +typedef struct uwac_pointer_source_event UwacPointerSourceEvent; + struct uwac_touch_frame_event { int type; @@ -286,6 +305,8 @@ union uwac_event { UwacPointerMotionEvent mouse_motion; UwacPointerButtonEvent mouse_button; UwacPointerAxisEvent mouse_axis; + UwacPointerFrameEvent mouse_frame; + UwacPointerSourceEvent mouse_source; UwacKeyboardEnterLeaveEvent keyboard_enter_leave; UwacKeyboardModifiersEvent keyboard_modifiers; UwacClipboardEvent clipboard; diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c index 6854092..0d448c3 100644 --- a/uwac/libuwac/uwac-input.c +++ b/uwac/libuwac/uwac-input.c @@ -846,12 +846,37 @@ static void pointer_handle_axis(void* data, struct wl_pointer* pointer, uint32_t static void pointer_frame(void* data, struct wl_pointer* wl_pointer) { - /*UwacSeat *seat = data;*/ + UwacPointerFrameEvent* event; + UwacSeat* seat = data; + UwacWindow* window = seat->pointer_focus; + + if (!window) + return; + + event = (UwacPointerFrameEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_FRAME); + if (!event) + return; + + event->seat = seat; + event->window = window; } static void pointer_axis_source(void* data, struct wl_pointer* wl_pointer, uint32_t axis_source) { - /*UwacSeat *seat = data;*/ + UwacPointerSourceEvent* event; + UwacSeat* seat = data; + UwacWindow* window = seat->pointer_focus; + + if (!window) + return; + + event = (UwacPointerSourceEvent*)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_SOURCE); + if (!event) + return; + + event->seat = seat; + event->window = window; + event->axis_source = axis_source; } static void pointer_axis_stop(void* data, struct wl_pointer* wl_pointer, uint32_t time, diff --git a/uwac/libuwac/uwac-window.c b/uwac/libuwac/uwac-window.c index d503755..c1e2b79 100644 --- a/uwac/libuwac/uwac-window.c +++ b/uwac/libuwac/uwac-window.c @@ -320,14 +320,14 @@ int UwacWindowShmAllocBuffers(UwacWindow* w, int nbuffers, int allocSize, uint32 w->buffers = newBuffers; memset(w->buffers + w->nbuffers, 0, sizeof(UwacBuffer) * nbuffers); - fd = uwac_create_anonymous_file(allocSize * nbuffers * 1ULL); + fd = uwac_create_anonymous_file(1ull * allocSize * nbuffers); if (fd < 0) { return UWAC_ERROR_INTERNAL; } - data = mmap(NULL, allocSize * nbuffers * 1ULL, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + data = mmap(NULL, 1ull * allocSize * nbuffers, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data == MAP_FAILED) { @@ -339,7 +339,7 @@ int UwacWindowShmAllocBuffers(UwacWindow* w, int nbuffers, int allocSize, uint32 if (!pool) { - munmap(data, allocSize * nbuffers * 1ULL); + munmap(data, 1ull * allocSize * nbuffers); ret = UWAC_ERROR_NOMEMORY; goto error_mmap; } @@ -764,7 +764,7 @@ UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, bool copyContentForNex if (copyContentForNextFrame) memcpy(nextDrawingBuffer->data, pendingBuffer->data, - window->stride * window->height * 1ULL); + 1ull * window->stride * window->height); UwacSubmitBufferPtr(window, pendingBuffer); return UWAC_SUCCESS; diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index 7b3ef1a..34dd6df 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -57,7 +57,7 @@ if (NOT WIN32) endif() # Soname versioning -set(RAW_VERSION_STRING "2.10.0") +set(RAW_VERSION_STRING "2.11.2") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) diff --git a/winpr/include/winpr/wtypes.h.in b/winpr/include/winpr/wtypes.h.in index d264890..c868095 100644 --- a/winpr/include/winpr/wtypes.h.in +++ b/winpr/include/winpr/wtypes.h.in @@ -161,8 +161,9 @@ typedef void* PVOID, *LPVOID, *PVOID64, *LPVOID64; #ifndef __APPLE__ typedef __int32 BOOL; #else /* __APPLE__ */ +#include /* ensure compatibility with objc libraries */ -#if (TARGET_OS_IPHONE && __LP64__) || TARGET_OS_WATCH +#if (defined(TARGET_OS_IPHONE) && (TARGET_OS_IPHONE != 0) && defined(__LP64__)) || (defined(TARGET_OS_WATCH) && (TARGET_OS_WATCH != 0)) typedef bool BOOL; #else typedef signed char BOOL; diff --git a/winpr/libwinpr/credui/CMakeLists.txt b/winpr/libwinpr/credui/CMakeLists.txt index b01be1d..886fe12 100644 --- a/winpr/libwinpr/credui/CMakeLists.txt +++ b/winpr/libwinpr/credui/CMakeLists.txt @@ -19,8 +19,8 @@ winpr_module_add(credui.c) if(WIN32) winpr_library_add_public(credui) -endif() - -if(BUILD_TESTING) - add_subdirectory(test) +else() + if(BUILD_TESTING) + add_subdirectory(test) + endif() endif() diff --git a/winpr/libwinpr/utils/collections/ArrayList.c b/winpr/libwinpr/utils/collections/ArrayList.c index f8fc3df..cb7e39a 100644 --- a/winpr/libwinpr/utils/collections/ArrayList.c +++ b/winpr/libwinpr/utils/collections/ArrayList.c @@ -233,6 +233,18 @@ BOOL ArrayList_Contains(wArrayList* arrayList, void* obj) * Adds an object to the end of the ArrayList. */ +static int insert(wArrayList* arrayList, size_t index, void* obj) +{ + if (arrayList->object.fnObjectNew) + { + obj = arrayList->object.fnObjectNew(obj); + arrayList->array[index] = obj; + } + else + arrayList->array[index] = obj; + return index + 1; +} + int ArrayList_Add(wArrayList* arrayList, void* obj) { int index = -1; @@ -253,8 +265,7 @@ int ArrayList_Add(wArrayList* arrayList, void* obj) arrayList->capacity = newCapacity; } - arrayList->array[arrayList->size++] = obj; - index = arrayList->size; + index = arrayList->size = insert(arrayList, arrayList->size, obj); out: if (arrayList->synchronized) @@ -282,7 +293,7 @@ BOOL ArrayList_Insert(wArrayList* arrayList, int index, void* obj) } else { - arrayList->array[index] = obj; + insert(arrayList, index, obj); } } diff --git a/winpr/libwinpr/utils/lodepng/lodepng.c b/winpr/libwinpr/utils/lodepng/lodepng.c index 2dd526a..b5c2307 100644 --- a/winpr/libwinpr/utils/lodepng/lodepng.c +++ b/winpr/libwinpr/utils/lodepng/lodepng.c @@ -3815,7 +3815,7 @@ unsigned lodepng_convert(unsigned char* out, const unsigned char* in, LodePNGCol { size_t i; ColorTree tree; - size_t numpixels = w * h * 1ULL; + size_t numpixels = 1ull * w * h; if (lodepng_color_mode_equal(mode_out, mode_in)) { @@ -3918,7 +3918,7 @@ unsigned get_color_profile(LodePNGColorProfile* profile, const unsigned char* in unsigned error = 0; size_t i; ColorTree tree; - size_t numpixels = w * h * 1ULL; + size_t numpixels = 1ull * w * h; unsigned colored_done = lodepng_is_greyscale_type(mode) ? 1 : 0; unsigned alpha_done = lodepng_can_have_alpha(mode) ? 0 : 1; @@ -4539,7 +4539,7 @@ static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, unsi if (bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) { CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp)); - removePaddingBits(out, in, w * bpp * 1ULL, ((w * bpp + 7ULL) / 8ULL) * 8ULL, h); + removePaddingBits(out, in, 1ull * w * bpp, ((w * bpp + 7ULL) / 8ULL) * 8ULL, h); } /*we can immediatly filter into the out buffer, no other steps needed*/ else @@ -4565,7 +4565,7 @@ static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, unsi bits between the different reduced images: each reduced image still starts nicely at a byte*/ removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], - passw[i] * bpp * 1ULL, ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL, + 1ull * passw[i] * bpp, ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL, passh[i]); } } @@ -6056,7 +6056,7 @@ static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const error = 83; /*alloc fail*/ if (!error) { - addPaddingBits(padded, in, ((w * bpp + 7ULL) / 8ULL) * 8ULL, w * bpp * 1ULL, h); + addPaddingBits(padded, in, ((w * bpp + 7ULL) / 8ULL) * 8ULL, 1ull * w * bpp, h); error = filter(*out, padded, w, h, &info_png->color, settings); } free(padded); @@ -6100,8 +6100,8 @@ static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const if (!padded) ERROR_BREAK(83); /*alloc fail*/ addPaddingBits(padded, &adam7[passstart[i]], - ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL, passw[i] * bpp * 1ULL, - passh[i] * 1ULL); + ((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL, 1ull * passw[i] * bpp, + 1ull * passh[i]); error = filter(&(*out)[filter_passstart[i]], padded, passw[i], passh[i], &info_png->color, settings); free(padded);