From b9853f87eb8998a5eb8b14ca0c4fcc540112d3d1 Mon Sep 17 00:00:00 2001 From: Martin Haimberger Date: Mon, 8 Jun 2015 05:44:10 -0700 Subject: [PATCH] channel encomsp hardend --- channels/encomsp/client/encomsp_main.c | 645 +++++++++++++++++-------- channels/encomsp/client/encomsp_main.h | 3 + channels/encomsp/server/encomsp_main.c | 120 +++-- client/X11/xf_client.c | 4 +- include/freerdp/client/encomsp.h | 25 +- include/freerdp/server/encomsp.h | 28 +- server/shadow/shadow_encomsp.c | 4 +- 7 files changed, 567 insertions(+), 262 deletions(-) diff --git a/channels/encomsp/client/encomsp_main.c b/channels/encomsp/client/encomsp_main.c index 9e93348d9..36648e304 100644 --- a/channels/encomsp/client/encomsp_main.c +++ b/channels/encomsp/client/encomsp_main.c @@ -3,6 +3,8 @@ * Multiparty Virtual Channel * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,43 +31,55 @@ #include "encomsp_main.h" -static int encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header) { if (Stream_GetRemainingLength(s) < ENCOMSP_ORDER_HEADER_SIZE) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT16(s, header->Type); /* Type (2 bytes) */ Stream_Read_UINT16(s, header->Length); /* Length (2 bytes) */ - return 1; + return CHANNEL_RC_OK; } -static int encomsp_write_header(wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_write_header(wStream* s, ENCOMSP_ORDER_HEADER* header) { Stream_Write_UINT16(s, header->Type); /* Type (2 bytes) */ Stream_Write_UINT16(s, header->Length); /* Length (2 bytes) */ - return 1; + return CHANNEL_RC_OK; } -static int encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str) +static WIN32ERROR encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str) { ZeroMemory(str, sizeof(ENCOMSP_UNICODE_STRING)); if (Stream_GetRemainingLength(s) < 2) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT16(s, str->cchString); /* cchString (2 bytes) */ if (str->cchString > 1024) - return -1; + { + WLog_ERR(TAG, "cchString was %d but has to be < 1025!", str->cchString); + return ERROR_INVALID_DATA; + } if (Stream_GetRemainingLength(s) < (size_t) (str->cchString * 2)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read(s, &(str->wString), (str->cchString * 2)); /* String (variable) */ - return 1; + return CHANNEL_RC_OK; } EncomspClientContext* encomsp_get_client_interface(encomspPlugin* encomsp) @@ -75,12 +89,12 @@ EncomspClientContext* encomsp_get_client_interface(encomspPlugin* encomsp) return pInterface; } -int encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s) +WIN32ERROR encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s) { - UINT32 status = 0; + WIN32ERROR status; if (!encomsp) - return -1; + return ERROR_INVALID_HANDLE; #if 0 WLog_INFO(TAG, "EncomspWrite (%d)", Stream_Length(s)); @@ -91,333 +105,407 @@ int encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s) Stream_Buffer(s), (UINT32) Stream_Length(s), s); if (status != CHANNEL_RC_OK) - { WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]", WTSErrorToString(status), status); - return -1; - } - return 1; + return status; } -static int encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_FILTER_UPDATED_PDU pdu; + WIN32ERROR error = CHANNEL_RC_OK; context = encomsp_get_client_interface(encomsp); if (!context) - return -1; + return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 1) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT8(s, pdu.Flags); /* Flags (1 byte) */ end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->FilterUpdated) - { - return context->FilterUpdated(context, &pdu); - } + IFCALLRET(context->FilterUpdated, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->FilterUpdated failed with error %lu", error); - return 1; + return error; } -static int encomsp_recv_application_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_application_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_APPLICATION_CREATED_PDU pdu; + WIN32ERROR error; context = encomsp_get_client_interface(encomsp); if (!context) - return -1; + return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 6) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */ - if (encomsp_read_unicode_string(s, &(pdu.Name)) < 0) - return -1; + if ((error = encomsp_read_unicode_string(s, &(pdu.Name)) )) + { + WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %lu", error); + return error; + } end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->ApplicationCreated) - { - return context->ApplicationCreated(context, &pdu); - } + IFCALLRET(context->ApplicationCreated, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->ApplicationCreated failed with error %lu", error); - return 1; + return error; } -static int encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_APPLICATION_REMOVED_PDU pdu; + WIN32ERROR error = CHANNEL_RC_OK; context = encomsp_get_client_interface(encomsp); if (!context) - return -1; + return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 4) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */ end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->ApplicationRemoved) - { - return context->ApplicationRemoved(context, &pdu); - } + IFCALLRET(context->ApplicationRemoved, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->ApplicationRemoved failed with error %lu", error); - return 1; + return error; } -static int encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_WINDOW_CREATED_PDU pdu; + WIN32ERROR error; context = encomsp_get_client_interface(encomsp); if (!context) - return -1; + return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 10) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */ Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */ - if (encomsp_read_unicode_string(s, &(pdu.Name)) < 0) - return -1; + if ((error = encomsp_read_unicode_string(s, &(pdu.Name)))) + { + WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %lu", error); + return error; + } end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->WindowCreated) - { - return context->WindowCreated(context, &pdu); - } + IFCALLRET(context->WindowCreated, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->WindowCreated failed with error %lu", error); - return 1; + return error; } -static int encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_WINDOW_REMOVED_PDU pdu; + WIN32ERROR error = CHANNEL_RC_OK; context = encomsp_get_client_interface(encomsp); if (!context) - return -1; + return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 4) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */ end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->WindowRemoved) - { - return context->WindowRemoved(context, &pdu); - } + IFCALLRET(context->WindowRemoved, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->WindowRemoved failed with error %lu", error); - return 1; + return error; } -static int encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_SHOW_WINDOW_PDU pdu; + WIN32ERROR error = CHANNEL_RC_OK; context = encomsp_get_client_interface(encomsp); if (!context) - return -1; + return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 4) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */ end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->ShowWindow) - { - return context->ShowWindow(context, &pdu); - } + IFCALLRET(context->ShowWindow, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->ShowWindow failed with error %lu", error); - return 1; + return error; } -static int encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_PARTICIPANT_CREATED_PDU pdu; + WIN32ERROR error; context = encomsp_get_client_interface(encomsp); if (!context) - return -1; + return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 10) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */ Stream_Read_UINT32(s, pdu.GroupId); /* GroupId (4 bytes) */ Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ - if (encomsp_read_unicode_string(s, &(pdu.FriendlyName)) < 0) - return -1; + + if ((error = encomsp_read_unicode_string(s, &(pdu.FriendlyName)))) + { + WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %lu", error); + return error; + } end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->ParticipantCreated) - { - return context->ParticipantCreated(context, &pdu); - } + IFCALLRET(context->ParticipantCreated, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->ParticipantCreated failed with error %lu", error); - return 1; + return error; } -static int encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_PARTICIPANT_REMOVED_PDU pdu; + WIN32ERROR error = CHANNEL_RC_OK; context = encomsp_get_client_interface(encomsp); if (!context) - return -1; + return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 12) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */ Stream_Read_UINT32(s, pdu.DiscType); /* DiscType (4 bytes) */ @@ -426,41 +514,50 @@ static int encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, wStream* end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->ParticipantRemoved) - { - return context->ParticipantRemoved(context, &pdu); - } + IFCALLRET(context->ParticipantRemoved, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->ParticipantRemoved failed with error %lu", error); - return 1; + return error; } -static int encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu; + WIN32ERROR error = CHANNEL_RC_OK; context = encomsp_get_client_interface(encomsp); if (!context) - return -1; + return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 6) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */ @@ -468,28 +565,34 @@ static int encomsp_recv_change_participant_control_level_pdu(encomspPlugin* enco end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->ChangeParticipantControlLevel) - { - return context->ChangeParticipantControlLevel(context, &pdu); - } + IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %lu", error); - return 1; + return error; } -static int encomsp_send_change_participant_control_level_pdu(EncomspClientContext* context, ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* pdu) +static WIN32ERROR encomsp_send_change_participant_control_level_pdu(EncomspClientContext* context, ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* pdu) { wStream* s; encomspPlugin* encomsp; + WIN32ERROR error; encomsp = (encomspPlugin*) context->handle; @@ -497,29 +600,37 @@ static int encomsp_send_change_participant_control_level_pdu(EncomspClientContex pdu->Length = ENCOMSP_ORDER_HEADER_SIZE + 6; s = Stream_New(NULL, pdu->Length); + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } - encomsp_write_header(s, (ENCOMSP_ORDER_HEADER*) pdu); + if ((error = encomsp_write_header(s, (ENCOMSP_ORDER_HEADER*) pdu))) + { + WLog_ERR(TAG, "encomsp_write_header failed with error %lu!", error); + return error; + } Stream_Write_UINT16(s, pdu->Flags); /* Flags (2 bytes) */ Stream_Write_UINT32(s, pdu->ParticipantId); /* ParticipantId (4 bytes) */ Stream_SealLength(s); - encomsp_virtual_channel_write(encomsp, s); - - return 1; + return encomsp_virtual_channel_write(encomsp, s); } -static int encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU pdu; + WIN32ERROR error = CHANNEL_RC_OK; context = encomsp_get_client_interface(encomsp); if (!context) - return -1; + return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; @@ -528,34 +639,40 @@ static int encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, wStre end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->GraphicsStreamPaused) - { - return context->GraphicsStreamPaused(context, &pdu); - } + IFCALLRET(context->GraphicsStreamPaused, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->GraphicsStreamPaused failed with error %lu", error); - return 1; + return error; } -static int encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; EncomspClientContext* context; ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU pdu; + WIN32ERROR error = CHANNEL_RC_OK; context = encomsp_get_client_interface(encomsp); if (!context) - return -1; + return ERROR_INVALID_HANDLE; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; @@ -564,92 +681,142 @@ static int encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp, wStr end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->GraphicsStreamResumed) - { - return context->GraphicsStreamResumed(context, &pdu); - } + IFCALLRET(context->GraphicsStreamResumed, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->GraphicsStreamResumed failed with error %lu", error); - return 1; + return error; } -static int encomsp_process_receive(encomspPlugin* encomsp, wStream* s) +static WIN32ERROR encomsp_process_receive(encomspPlugin* encomsp, wStream* s) { - int status = 1; + WIN32ERROR error = CHANNEL_RC_OK; ENCOMSP_ORDER_HEADER header; while (Stream_GetRemainingLength(s) > 0) { - if (encomsp_read_header(s, &header) < 0) - return -1; + if ((error = encomsp_read_header(s, &header))) + { + WLog_ERR(TAG, "encomsp_read_header failed with error %lu!", error); + return error; + } //WLog_DBG(TAG, "EncomspReceive: Type: %d Length: %d", header.Type, header.Length); switch (header.Type) { case ODTYPE_FILTER_STATE_UPDATED: - status = encomsp_recv_filter_updated_pdu(encomsp, s, &header); + if ((error = encomsp_recv_filter_updated_pdu(encomsp, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_filter_updated_pdu failed with error %lu!", error); + return error; + } break; case ODTYPE_APP_REMOVED: - status = encomsp_recv_application_removed_pdu(encomsp, s, &header); + if ((error = encomsp_recv_application_removed_pdu(encomsp, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %lu!", error); + return error; + } break; case ODTYPE_APP_CREATED: - status = encomsp_recv_application_created_pdu(encomsp, s, &header); + if ((error = encomsp_recv_application_created_pdu(encomsp, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %lu!", error); + return error; + } break; case ODTYPE_WND_REMOVED: - status = encomsp_recv_window_removed_pdu(encomsp, s, &header); + if ((error = encomsp_recv_window_removed_pdu(encomsp, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_window_removed_pdu failed with error %lu!", error); + return error; + } break; case ODTYPE_WND_CREATED: - status = encomsp_recv_window_created_pdu(encomsp, s, &header); + if ((error = encomsp_recv_window_created_pdu(encomsp, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_window_created_pdu failed with error %lu!", error); + return error; + } break; case ODTYPE_WND_SHOW: - status = encomsp_recv_show_window_pdu(encomsp, s, &header); + if ((error = encomsp_recv_show_window_pdu(encomsp, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_show_window_pdu failed with error %lu!", error); + return error; + } break; case ODTYPE_PARTICIPANT_REMOVED: - status = encomsp_recv_participant_removed_pdu(encomsp, s, &header); + if ((error = encomsp_recv_participant_removed_pdu(encomsp, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_participant_removed_pdu failed with error %lu!", error); + return error; + } break; case ODTYPE_PARTICIPANT_CREATED: - status = encomsp_recv_participant_created_pdu(encomsp, s, &header); + if ((error = encomsp_recv_participant_created_pdu(encomsp, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_participant_created_pdu failed with error %lu!", error); + return error; + } break; case ODTYPE_PARTICIPANT_CTRL_CHANGED: - status = encomsp_recv_change_participant_control_level_pdu(encomsp, s, &header); + if ((error = encomsp_recv_change_participant_control_level_pdu(encomsp, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_change_participant_control_level_pdu failed with error %lu!", error); + return error; + } break; case ODTYPE_GRAPHICS_STREAM_PAUSED: - status = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header); + if ((error = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_graphics_stream_paused_pdu failed with error %lu!", error); + return error; + } break; case ODTYPE_GRAPHICS_STREAM_RESUMED: - status = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header); + if ((error = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_graphics_stream_resumed_pdu failed with error %lu!", error); + return error; + } break; default: - status = -1; + WLog_ERR(TAG, "header.Type %d not found", header.Type); + return ERROR_INVALID_DATA; break; } - if (status < 0) - return -1; } - - return status; + return error; } static void encomsp_process_connect(encomspPlugin* encomsp) @@ -662,16 +829,24 @@ static void encomsp_process_connect(encomspPlugin* encomsp) static wListDictionary* g_InitHandles = NULL; static wListDictionary* g_OpenHandles = NULL; -BOOL encomsp_add_init_handle_data(void* pInitHandle, void* pUserData) +WIN32ERROR encomsp_add_init_handle_data(void* pInitHandle, void* pUserData) { if (!g_InitHandles) { g_InitHandles = ListDictionary_New(TRUE); - if (!g_InitHandles) - return FALSE; + } + if (!g_InitHandles) + { + WLog_ERR(TAG, "ListDictionary_New failed!"); + return CHANNEL_RC_NO_MEMORY; } - return ListDictionary_Add(g_InitHandles, pInitHandle, pUserData); + if (!ListDictionary_Add(g_InitHandles, pInitHandle, pUserData)) + { + WLog_ERR(TAG, "ListDictionary_Add failed!"); + return ERROR_INTERNAL_ERROR; + } + return CHANNEL_RC_OK; } void* encomsp_get_init_handle_data(void* pInitHandle) @@ -691,18 +866,27 @@ void encomsp_remove_init_handle_data(void* pInitHandle) } } -BOOL encomsp_add_open_handle_data(DWORD openHandle, void* pUserData) +WIN32ERROR encomsp_add_open_handle_data(DWORD openHandle, void* pUserData) { void* pOpenHandle = (void*) (size_t) openHandle; if (!g_OpenHandles) { g_OpenHandles = ListDictionary_New(TRUE); - if (!g_OpenHandles) - return FALSE; } - return ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData); + if (!g_OpenHandles) + { + WLog_ERR(TAG, "ListDictionary_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + if (!ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData)) + { + WLog_ERR(TAG, "ListDictionary_Add failed!"); + return ERROR_INTERNAL_ERROR; + } + return CHANNEL_RC_OK; } void* encomsp_get_open_handle_data(DWORD openHandle) @@ -749,15 +933,13 @@ int encomsp_send(encomspPlugin* encomsp, wStream* s) return status; } -static void encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, +static WIN32ERROR encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { wStream* data_in; if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME)) - { - return; - } + return CHANNEL_RC_OK; if (dataFlags & CHANNEL_FLAG_FIRST) { @@ -765,10 +947,19 @@ static void encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, Stream_Free(encomsp->data_in, TRUE); encomsp->data_in = Stream_New(NULL, totalLength); + if (!encomsp->data_in) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } } data_in = encomsp->data_in; - Stream_EnsureRemainingCapacity(data_in, (int) dataLength); + if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + return ERROR_INTERNAL_ERROR; + } Stream_Write(data_in, pData, dataLength); if (dataFlags & CHANNEL_FLAG_LAST) @@ -776,6 +967,7 @@ static void encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { WLog_ERR(TAG, "encomsp_plugin_process_received: read error"); + return ERROR_INVALID_DATA; } encomsp->data_in = NULL; @@ -784,6 +976,7 @@ static void encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, MessageQueue_Post(encomsp->queue, NULL, 0, (void*) data_in, NULL); } + return CHANNEL_RC_OK; } static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle, UINT event, @@ -796,13 +989,20 @@ static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle, UINT if (!encomsp) { WLog_ERR(TAG, "encomsp_virtual_channel_open_event: error no match"); + encomsp->error = CHANNEL_RC_BAD_CHANNEL; return; } + encomsp->error = CHANNEL_RC_OK; + switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength, totalLength, dataFlags); + if ((encomsp->error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength, totalLength, dataFlags))) + { + WLog_ERR(TAG, "encomsp_virtual_channel_event_data_received failed with error %lu", encomsp->error); + return; + } break; case CHANNEL_EVENT_WRITE_COMPLETE: @@ -812,6 +1012,8 @@ static VOID VCAPITYPE encomsp_virtual_channel_open_event(DWORD openHandle, UINT case CHANNEL_EVENT_USER: break; } + return; + //TODO erport error } static void* encomsp_virtual_channel_client_thread(void* arg) @@ -819,6 +1021,7 @@ static void* encomsp_virtual_channel_client_thread(void* arg) wStream* data; wMessage message; encomspPlugin* encomsp = (encomspPlugin*) arg; + WIN32ERROR error = CHANNEL_RC_OK; encomsp_process_connect(encomsp); @@ -835,53 +1038,58 @@ static void* encomsp_virtual_channel_client_thread(void* arg) if (message.id == 0) { data = (wStream*) message.wParam; - encomsp_process_receive(encomsp, data); + if ((error = encomsp_process_receive(encomsp, data))) + { + WLog_ERR(TAG, "encomsp_process_receive failed with error %lu!", error); + break; + } } } } - ExitThread(0); + ExitThread((DWORD)error); return NULL; } -static void encomsp_virtual_channel_event_connected(encomspPlugin* encomsp, LPVOID pData, UINT32 dataLength) +static WIN32ERROR encomsp_virtual_channel_event_connected(encomspPlugin* encomsp, LPVOID pData, UINT32 dataLength) { UINT32 status; + WIN32ERROR error; status = encomsp->channelEntryPoints.pVirtualChannelOpen(encomsp->InitHandle, &encomsp->OpenHandle, encomsp->channelDef.name, encomsp_virtual_channel_open_event); - if (!encomsp_add_open_handle_data(encomsp->OpenHandle, encomsp)) - { - WLog_ERR(TAG, "%s: unable to register open handle", __FUNCTION__); - return; - } - if (status != CHANNEL_RC_OK) { - WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]", + WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]", WTSErrorToString(status), status); - return; + return status; + } + + if ((error = encomsp_add_open_handle_data(encomsp->OpenHandle, encomsp))) + { + WLog_ERR(TAG, "encomsp_process_receive failed with error %lu!", error); + return status; } encomsp->queue = MessageQueue_New(NULL); if (!encomsp->queue) { - WLog_ERR(TAG, "%s: unable to create message queue", __FUNCTION__); - return; + WLog_ERR(TAG, "MessageQueue_New failed!"); + return CHANNEL_RC_NO_MEMORY; } - encomsp->thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) encomsp_virtual_channel_client_thread, (void*) encomsp, 0, NULL); - if (!encomsp->thread) + if (!(encomsp->thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) encomsp_virtual_channel_client_thread, (void*) encomsp, 0, NULL))) { - WLog_ERR(TAG, "%s: unable to create thread", __FUNCTION__); - return; + WLog_ERR(TAG, "CreateThread failed!"); + MessageQueue_Free(encomsp->queue); + return ERROR_INTERNAL_ERROR; } - + return CHANNEL_RC_OK; } -static void encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp) +static WIN32ERROR encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp) { UINT rc; MessageQueue_PostQuit(encomsp->queue, 0); @@ -898,6 +1106,7 @@ static void encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp) { WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]", WTSErrorToString(rc), rc); + return rc; } if (encomsp->data_in) @@ -907,16 +1116,18 @@ static void encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp) } encomsp_remove_open_handle_data(encomsp->OpenHandle); + return CHANNEL_RC_OK; } -static void encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp) +static WIN32ERROR encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp) { encomsp_remove_init_handle_data(encomsp->InitHandle); free(encomsp); + return CHANNEL_RC_OK; } -static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) +static void VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { encomspPlugin* encomsp; @@ -925,23 +1136,40 @@ static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UIN if (!encomsp) { WLog_ERR(TAG, "encomsp_virtual_channel_init_event: error no match"); + encomsp->error = CHANNEL_RC_BAD_CHANNEL; return; } + encomsp->error = CHANNEL_RC_OK; + switch (event) { case CHANNEL_EVENT_CONNECTED: - encomsp_virtual_channel_event_connected(encomsp, pData, dataLength); + if ((encomsp->error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength))) + { + WLog_ERR(TAG, "encomsp_virtual_channel_event_connected failed with error %lu", encomsp->error); + return; + } break; case CHANNEL_EVENT_DISCONNECTED: - encomsp_virtual_channel_event_disconnected(encomsp); + if ((encomsp->error = encomsp_virtual_channel_event_disconnected(encomsp))) + { + WLog_ERR(TAG, "encomsp_virtual_channel_event_disconnected failed with error %lu", encomsp->error); + return; + } break; case CHANNEL_EVENT_TERMINATED: encomsp_virtual_channel_event_terminated(encomsp); break; + default: + WLog_ERR(TAG, "uknown event type %d", event); + encomsp->error = ERROR_INVALID_DATA; + return; } + return; + //TODO report error } /* encomsp is always built-in */ @@ -953,8 +1181,14 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) encomspPlugin* encomsp; EncomspClientContext* context; CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx; + BOOL isFreerdp = FALSE; encomsp = (encomspPlugin*) calloc(1, sizeof(encomspPlugin)); + if (!encomsp) + { + WLog_ERR(TAG, "calloc failed!"); + return FALSE; + } encomsp->channelDef.options = CHANNEL_OPTION_INITIALIZED | @@ -970,6 +1204,11 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { context = (EncomspClientContext*) calloc(1, sizeof(EncomspClientContext)); + if (!context) + { + WLog_ERR(TAG, "calloc failed!"); + goto error_out; + } context->handle = (void*) encomsp; @@ -987,6 +1226,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) *(pEntryPointsEx->ppInterface) = (void*) context; encomsp->context = context; + isFreerdp = TRUE; } CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP)); @@ -997,11 +1237,22 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) { WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]", WTSErrorToString(rc), rc); - free(encomsp); - return -1; + goto error_out; } + encomsp->channelEntryPoints.pInterface = *(encomsp->channelEntryPoints.ppInterface); encomsp->channelEntryPoints.ppInterface = &(encomsp->channelEntryPoints.pInterface); - return encomsp_add_init_handle_data(encomsp->InitHandle, (void*) encomsp); + if ((encomsp->error = encomsp_add_init_handle_data(encomsp->InitHandle, (void*) encomsp))) + { + WLog_ERR(TAG, "encomsp_add_init_handle_data failed with error %lu!", encomsp->error); + goto error_out; + } + + return TRUE; +error_out: + if (isFreerdp) + free(encomsp->context); + free(encomsp); + return FALSE; } diff --git a/channels/encomsp/client/encomsp_main.h b/channels/encomsp/client/encomsp_main.h index 444c0bc2f..5aea1b297 100644 --- a/channels/encomsp/client/encomsp_main.h +++ b/channels/encomsp/client/encomsp_main.h @@ -3,6 +3,8 @@ * Multiparty Virtual Channel * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,6 +49,7 @@ struct encomsp_plugin void* InitHandle; DWORD OpenHandle; wMessageQueue* queue; + WIN32ERROR error; }; typedef struct encomsp_plugin encomspPlugin; diff --git a/channels/encomsp/server/encomsp_main.c b/channels/encomsp/server/encomsp_main.c index b15bff42c..6547815fb 100644 --- a/channels/encomsp/server/encomsp_main.c +++ b/channels/encomsp/server/encomsp_main.c @@ -3,6 +3,8 @@ * Multiparty Virtual Channel * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,15 +33,15 @@ #define TAG CHANNELS_TAG("encomsp.server") -static int encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header) { if (Stream_GetRemainingLength(s) < ENCOMSP_ORDER_HEADER_SIZE) - return -1; + return ERROR_INVALID_DATA; Stream_Read_UINT16(s, header->Type); /* Type (2 bytes) */ Stream_Read_UINT16(s, header->Length); /* Length (2 bytes) */ - return 1; + return CHANNEL_RC_OK; } #if 0 @@ -74,17 +76,21 @@ static int encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str) #endif -static int encomsp_recv_change_participant_control_level_pdu(EncomspServerContext* context, wStream* s, ENCOMSP_ORDER_HEADER* header) +static WIN32ERROR encomsp_recv_change_participant_control_level_pdu(EncomspServerContext* context, wStream* s, ENCOMSP_ORDER_HEADER* header) { int beg, end; ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu; + WIN32ERROR error = CHANNEL_RC_OK; beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 6) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */ @@ -92,58 +98,68 @@ static int encomsp_recv_change_participant_control_level_pdu(EncomspServerContex end = (int) Stream_GetPosition(s); if ((beg + header->Length) < end) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } if ((beg + header->Length) > end) { if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end)) - return -1; + { + WLog_ERR(TAG, "Not enought data!"); + return ERROR_INVALID_DATA; + } Stream_SetPosition(s, (beg + header->Length)); } - if (context->ChangeParticipantControlLevel) - { - return context->ChangeParticipantControlLevel(context, &pdu); - } + IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu); + if (error) + WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %lu", error); - return 1; + return error; } -static int encomsp_server_receive_pdu(EncomspServerContext* context, wStream* s) +static WIN32ERROR encomsp_server_receive_pdu(EncomspServerContext* context, wStream* s) { - int status = 1; + WIN32ERROR error = CHANNEL_RC_OK; ENCOMSP_ORDER_HEADER header; while (Stream_GetRemainingLength(s) > 0) { - if (encomsp_read_header(s, &header) < 0) - return -1; + if ((error = encomsp_read_header(s, &header))) + { + WLog_ERR(TAG, "encomsp_read_header failed with error %lu!", error); + return error; + } WLog_INFO(TAG, "EncomspReceive: Type: %d Length: %d", header.Type, header.Length); switch (header.Type) { case ODTYPE_PARTICIPANT_CTRL_CHANGED: - status = encomsp_recv_change_participant_control_level_pdu(context, s, &header); + if ((error = encomsp_recv_change_participant_control_level_pdu(context, s, &header))) + { + WLog_ERR(TAG, "encomsp_recv_change_participant_control_level_pdu failed with error %lu!", error); + return error; + } + break; default: - status = -1; + WLog_ERR(TAG, "header.Type unknown %d!", header.Type); + return ERROR_INVALID_DATA; break; } - - if (status < 0) - return -1; } - return status; + return error; } static void* encomsp_server_thread(void* arg) { wStream* s; - DWORD status; DWORD nCount; void* buffer; HANDLE events[8]; @@ -151,6 +167,7 @@ static void* encomsp_server_thread(void* arg) DWORD BytesReturned; ENCOMSP_ORDER_HEADER* header; EncomspServerContext* context; + WIN32ERROR error = CHANNEL_RC_OK; context = (EncomspServerContext*) arg; @@ -159,6 +176,12 @@ static void* encomsp_server_thread(void* arg) ChannelEvent = NULL; s = Stream_New(NULL, 4096); + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + ExitThread((DWORD) CHANNEL_RC_NO_MEMORY); + return NULL; + } if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE) { @@ -174,7 +197,7 @@ static void* encomsp_server_thread(void* arg) while (1) { - status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); + WaitForMultipleObjects(nCount, events, FALSE, INFINITE); if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) { @@ -184,10 +207,17 @@ static void* encomsp_server_thread(void* arg) WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned); if (BytesReturned < 1) continue; - Stream_EnsureRemainingCapacity(s, BytesReturned); + if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + error = CHANNEL_RC_NO_MEMORY; + break; + } if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) { + WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); + error = ERROR_INTERNAL_ERROR; break; } @@ -199,40 +229,54 @@ static void* encomsp_server_thread(void* arg) { Stream_SealLength(s); Stream_SetPosition(s, 0); - encomsp_server_receive_pdu(context, s); + if ((error = encomsp_server_receive_pdu(context, s))) + { + WLog_ERR(TAG, "encomsp_server_receive_pdu failed with error %lu!", error); + break; + } Stream_SetPosition(s, 0); } } } Stream_Free(s, TRUE); - + ExitThread((DWORD)error); return NULL; } -static int encomsp_server_start(EncomspServerContext* context) +static WIN32ERROR encomsp_server_start(EncomspServerContext* context) { context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "encomsp"); if (!context->priv->ChannelHandle) - return -1; + return CHANNEL_RC_BAD_CHANNEL; - context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!(context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + { + WLog_ERR(TAG, "CreateEvent failed!"); + return ERROR_INTERNAL_ERROR; + } - context->priv->Thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE) encomsp_server_thread, (void*) context, 0, NULL); + if (!(context->priv->Thread = CreateThread(NULL, 0, + (LPTHREAD_START_ROUTINE) encomsp_server_thread, (void*) context, 0, NULL))) + { + WLog_ERR(TAG, "CreateThread failed!"); + CloseHandle(context->priv->StopEvent); + context->priv->StopEvent = NULL; + return ERROR_INTERNAL_ERROR; + } - return 0; + return CHANNEL_RC_OK; } -static int encomsp_server_stop(EncomspServerContext* context) +static WIN32ERROR encomsp_server_stop(EncomspServerContext* context) { SetEvent(context->priv->StopEvent); WaitForSingleObject(context->priv->Thread, INFINITE); CloseHandle(context->priv->Thread); - return 0; + return CHANNEL_RC_OK; } EncomspServerContext* encomsp_server_context_new(HANDLE vcm) @@ -250,9 +294,11 @@ EncomspServerContext* encomsp_server_context_new(HANDLE vcm) context->priv = (EncomspServerPrivate*) calloc(1, sizeof(EncomspServerPrivate)); - if (context->priv) + if (!context->priv) { - + WLog_ERR(TAG, "calloc failed!"); + free(context); + return NULL; } } diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 83868d68a..5a13ded31 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -723,9 +723,9 @@ void xf_toggle_control(xfContext* xfc) xfc->controlToggle = !xfc->controlToggle; } -int xf_encomsp_participant_created(EncomspClientContext* context, ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated) +WIN32ERROR xf_encomsp_participant_created(EncomspClientContext* context, ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated) { - return 1; + return CHANNEL_RC_OK; } void xf_encomsp_init(xfContext* xfc, EncomspClientContext* encomsp) diff --git a/include/freerdp/client/encomsp.h b/include/freerdp/client/encomsp.h index e8b8466e1..f2230a576 100644 --- a/include/freerdp/client/encomsp.h +++ b/include/freerdp/client/encomsp.h @@ -3,6 +3,8 @@ * Multiparty Virtual Channel * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +23,7 @@ #define FREERDP_CHANNEL_CLIENT_ENCOMSP_H #include +#include /** * Client Interface @@ -28,17 +31,17 @@ typedef struct _encomsp_client_context EncomspClientContext; -typedef int (*pcEncomspFilterUpdated)(EncomspClientContext* context, ENCOMSP_FILTER_UPDATED_PDU* filterUpdated); -typedef int (*pcEncomspApplicationCreated)(EncomspClientContext* context, ENCOMSP_APPLICATION_CREATED_PDU* applicationCreated); -typedef int (*pcEncomspApplicationRemoved)(EncomspClientContext* context, ENCOMSP_APPLICATION_REMOVED_PDU* applicationRemoved); -typedef int (*pcEncomspWindowCreated)(EncomspClientContext* context, ENCOMSP_WINDOW_CREATED_PDU* windowCreated); -typedef int (*pcEncomspWindowRemoved)(EncomspClientContext* context, ENCOMSP_WINDOW_REMOVED_PDU* windowRemoved); -typedef int (*pcEncomspShowWindow)(EncomspClientContext* context, ENCOMSP_SHOW_WINDOW_PDU* showWindow); -typedef int (*pcEncomspParticipantCreated)(EncomspClientContext* context, ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated); -typedef int (*pcEncomspParticipantRemoved)(EncomspClientContext* context, ENCOMSP_PARTICIPANT_REMOVED_PDU* participantRemoved); -typedef int (*pcEncomspChangeParticipantControlLevel)(EncomspClientContext* context, ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* changeParticipantControlLevel); -typedef int (*pcEncomspGraphicsStreamPaused)(EncomspClientContext* context, ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU* graphicsStreamPaused); -typedef int (*pcEncomspGraphicsStreamResumed)(EncomspClientContext* context, ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU* graphicsStreamResumed); +typedef WIN32ERROR (*pcEncomspFilterUpdated)(EncomspClientContext* context, ENCOMSP_FILTER_UPDATED_PDU* filterUpdated); +typedef WIN32ERROR (*pcEncomspApplicationCreated)(EncomspClientContext* context, ENCOMSP_APPLICATION_CREATED_PDU* applicationCreated); +typedef WIN32ERROR (*pcEncomspApplicationRemoved)(EncomspClientContext* context, ENCOMSP_APPLICATION_REMOVED_PDU* applicationRemoved); +typedef WIN32ERROR (*pcEncomspWindowCreated)(EncomspClientContext* context, ENCOMSP_WINDOW_CREATED_PDU* windowCreated); +typedef WIN32ERROR (*pcEncomspWindowRemoved)(EncomspClientContext* context, ENCOMSP_WINDOW_REMOVED_PDU* windowRemoved); +typedef WIN32ERROR (*pcEncomspShowWindow)(EncomspClientContext* context, ENCOMSP_SHOW_WINDOW_PDU* showWindow); +typedef WIN32ERROR (*pcEncomspParticipantCreated)(EncomspClientContext* context, ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated); +typedef WIN32ERROR (*pcEncomspParticipantRemoved)(EncomspClientContext* context, ENCOMSP_PARTICIPANT_REMOVED_PDU* participantRemoved); +typedef WIN32ERROR (*pcEncomspChangeParticipantControlLevel)(EncomspClientContext* context, ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* changeParticipantControlLevel); +typedef WIN32ERROR (*pcEncomspGraphicsStreamPaused)(EncomspClientContext* context, ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU* graphicsStreamPaused); +typedef WIN32ERROR (*pcEncomspGraphicsStreamResumed)(EncomspClientContext* context, ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU* graphicsStreamResumed); struct _encomsp_client_context { diff --git a/include/freerdp/server/encomsp.h b/include/freerdp/server/encomsp.h index a5037e628..678b3600e 100644 --- a/include/freerdp/server/encomsp.h +++ b/include/freerdp/server/encomsp.h @@ -3,6 +3,8 @@ * Multiparty Virtual Channel * * Copyright 2014 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,20 +35,20 @@ typedef struct _encomsp_server_context EncomspServerContext; typedef struct _encomsp_server_private EncomspServerPrivate; -typedef int (*psEncomspStart)(EncomspServerContext* context); -typedef int (*psEncomspStop)(EncomspServerContext* context); +typedef WIN32ERROR (*psEncomspStart)(EncomspServerContext* context); +typedef WIN32ERROR (*psEncomspStop)(EncomspServerContext* context); -typedef int (*psEncomspFilterUpdated)(EncomspServerContext* context, ENCOMSP_FILTER_UPDATED_PDU* filterUpdated); -typedef int (*psEncomspApplicationCreated)(EncomspServerContext* context, ENCOMSP_APPLICATION_CREATED_PDU* applicationCreated); -typedef int (*psEncomspApplicationRemoved)(EncomspServerContext* context, ENCOMSP_APPLICATION_REMOVED_PDU* applicationRemoved); -typedef int (*psEncomspWindowCreated)(EncomspServerContext* context, ENCOMSP_WINDOW_CREATED_PDU* windowCreated); -typedef int (*psEncomspWindowRemoved)(EncomspServerContext* context, ENCOMSP_WINDOW_REMOVED_PDU* windowRemoved); -typedef int (*psEncomspShowWindow)(EncomspServerContext* context, ENCOMSP_SHOW_WINDOW_PDU* showWindow); -typedef int (*psEncomspParticipantCreated)(EncomspServerContext* context, ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated); -typedef int (*psEncomspParticipantRemoved)(EncomspServerContext* context, ENCOMSP_PARTICIPANT_REMOVED_PDU* participantRemoved); -typedef int (*psEncomspChangeParticipantControlLevel)(EncomspServerContext* context, ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* changeParticipantControlLevel); -typedef int (*psEncomspGraphicsStreamPaused)(EncomspServerContext* context, ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU* graphicsStreamPaused); -typedef int (*psEncomspGraphicsStreamResumed)(EncomspServerContext* context, ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU* graphicsStreamResumed); +typedef WIN32ERROR (*psEncomspFilterUpdated)(EncomspServerContext* context, ENCOMSP_FILTER_UPDATED_PDU* filterUpdated); +typedef WIN32ERROR (*psEncomspApplicationCreated)(EncomspServerContext* context, ENCOMSP_APPLICATION_CREATED_PDU* applicationCreated); +typedef WIN32ERROR (*psEncomspApplicationRemoved)(EncomspServerContext* context, ENCOMSP_APPLICATION_REMOVED_PDU* applicationRemoved); +typedef WIN32ERROR (*psEncomspWindowCreated)(EncomspServerContext* context, ENCOMSP_WINDOW_CREATED_PDU* windowCreated); +typedef WIN32ERROR (*psEncomspWindowRemoved)(EncomspServerContext* context, ENCOMSP_WINDOW_REMOVED_PDU* windowRemoved); +typedef WIN32ERROR (*psEncomspShowWindow)(EncomspServerContext* context, ENCOMSP_SHOW_WINDOW_PDU* showWindow); +typedef WIN32ERROR (*psEncomspParticipantCreated)(EncomspServerContext* context, ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated); +typedef WIN32ERROR (*psEncomspParticipantRemoved)(EncomspServerContext* context, ENCOMSP_PARTICIPANT_REMOVED_PDU* participantRemoved); +typedef WIN32ERROR (*psEncomspChangeParticipantControlLevel)(EncomspServerContext* context, ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* changeParticipantControlLevel); +typedef WIN32ERROR (*psEncomspGraphicsStreamPaused)(EncomspServerContext* context, ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU* graphicsStreamPaused); +typedef WIN32ERROR (*psEncomspGraphicsStreamResumed)(EncomspServerContext* context, ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU* graphicsStreamResumed); struct _encomsp_server_context { diff --git a/server/shadow/shadow_encomsp.c b/server/shadow/shadow_encomsp.c index 61bb2e582..7e8cc2c86 100644 --- a/server/shadow/shadow_encomsp.c +++ b/server/shadow/shadow_encomsp.c @@ -27,7 +27,7 @@ #define TAG SERVER_TAG("shadow") -static int encomsp_change_participant_control_level(EncomspServerContext* context, +static WIN32ERROR encomsp_change_participant_control_level(EncomspServerContext* context, ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* pdu) { BOOL inLobby; @@ -90,7 +90,7 @@ static int encomsp_change_participant_control_level(EncomspServerContext* contex client->inLobby = inLobby; } - return 1; + return CHANNEL_RC_OK; } int shadow_client_encomsp_init(rdpShadowClient* client)