FreeRDP/libfreerdp/core/channels.c
Bernhard Miklautz f469e069dc stream: Stream_Ensure*Capacity: change return type
Change the return type of Stream_Ensure*Capacity from void to BOOL to be
able to detect realloc problems easily. Otherwise the only way to detect
this was to check if the capacity after the call was >= the required
size.
In case Stream_Ensure*Capacity fails the old memory is still available
and need to freed outside.

This commit also adds checks to most calls of Stream_Ensure*Capacity to
check if the call was successful.
2015-03-30 16:33:48 +02:00

268 lines
7.8 KiB
C

/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Virtual Channels
*
* Copyright 2011 Vic Lee
* Copyright 2015 Copyright 2015 Thincast Technologies GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <winpr/wtsapi.h>
#include <freerdp/freerdp.h>
#include <freerdp/constants.h>
#include <freerdp/log.h>
#include <freerdp/svc.h>
#include <freerdp/peer.h>
#include <freerdp/addin.h>
#include <freerdp/client/channels.h>
#include <freerdp/client/drdynvc.h>
#include <freerdp/channels/channels.h>
#include "rdp.h"
#include "client.h"
#include "server.h"
#include "channels.h"
#define TAG FREERDP_TAG("core.channels")
BOOL freerdp_channel_send(rdpRdp* rdp, UINT16 channelId, BYTE* data, int size)
{
DWORD i;
int left;
wStream* s;
UINT32 flags;
int chunkSize;
rdpMcs* mcs = rdp->mcs;
rdpMcsChannel* channel = NULL;
for (i = 0; i < mcs->channelCount; i++)
{
if (mcs->channels[i].ChannelId == channelId)
{
channel = &mcs->channels[i];
break;
}
}
if (!channel)
{
WLog_ERR(TAG, "freerdp_channel_send: unknown channelId %d", channelId);
return FALSE;
}
flags = CHANNEL_FLAG_FIRST;
left = size;
while (left > 0)
{
s = rdp_send_stream_init(rdp);
if (!s)
return FALSE;
if (left > (int) rdp->settings->VirtualChannelChunkSize)
{
chunkSize = rdp->settings->VirtualChannelChunkSize;
}
else
{
chunkSize = left;
flags |= CHANNEL_FLAG_LAST;
}
if ((channel->options & CHANNEL_OPTION_SHOW_PROTOCOL))
{
flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
}
Stream_Write_UINT32(s, size);
Stream_Write_UINT32(s, flags);
if(!Stream_EnsureCapacity(s, chunkSize))
{
Stream_Release(s);
return FALSE;
}
Stream_Write(s, data, chunkSize);
if(!rdp_send(rdp, s, channelId))
{
Stream_Release(s);
return FALSE;
}
data += chunkSize;
left -= chunkSize;
flags = 0;
}
return TRUE;
}
BOOL freerdp_channel_process(freerdp* instance, wStream* s, UINT16 channelId)
{
UINT32 length;
UINT32 flags;
int chunkLength;
if (Stream_GetRemainingLength(s) < 8)
return FALSE;
Stream_Read_UINT32(s, length);
Stream_Read_UINT32(s, flags);
chunkLength = Stream_GetRemainingLength(s);
IFCALL(instance->ReceiveChannelData, instance,
channelId, Stream_Pointer(s), chunkLength, flags, length);
return TRUE;
}
BOOL freerdp_channel_peer_process(freerdp_peer* client, wStream* s, UINT16 channelId)
{
UINT32 length;
UINT32 flags;
int chunkLength;
if (Stream_GetRemainingLength(s) < 8)
return FALSE;
Stream_Read_UINT32(s, length);
Stream_Read_UINT32(s, flags);
chunkLength = Stream_GetRemainingLength(s);
if (client->VirtualChannelRead)
{
UINT32 index;
BOOL found = FALSE;
HANDLE hChannel = 0;
rdpContext* context = client->context;
rdpMcs* mcs = context->rdp->mcs;
rdpMcsChannel* mcsChannel = NULL;
for (index = 0; index < mcs->channelCount; index++)
{
mcsChannel = &(mcs->channels[index]);
if (mcsChannel->ChannelId == channelId)
{
hChannel = (HANDLE) mcsChannel->handle;
found = TRUE;
break;
}
}
if (!found)
return FALSE;
client->VirtualChannelRead(client, hChannel, Stream_Pointer(s), Stream_GetRemainingLength(s));
}
else if (client->ReceiveChannelData)
{
client->ReceiveChannelData(client, channelId, Stream_Pointer(s), chunkLength, flags, length);
}
return TRUE;
}
static WtsApiFunctionTable FreeRDP_WtsApiFunctionTable =
{
0, /* dwVersion */
0, /* dwFlags */
FreeRDP_WTSStopRemoteControlSession, /* StopRemoteControlSession */
FreeRDP_WTSStartRemoteControlSessionW, /* StartRemoteControlSessionW */
FreeRDP_WTSStartRemoteControlSessionA, /* StartRemoteControlSessionA */
FreeRDP_WTSConnectSessionW, /* ConnectSessionW */
FreeRDP_WTSConnectSessionA, /* ConnectSessionA */
FreeRDP_WTSEnumerateServersW, /* EnumerateServersW */
FreeRDP_WTSEnumerateServersA, /* EnumerateServersA */
FreeRDP_WTSOpenServerW, /* OpenServerW */
FreeRDP_WTSOpenServerA, /* OpenServerA */
FreeRDP_WTSOpenServerExW, /* OpenServerExW */
FreeRDP_WTSOpenServerExA, /* OpenServerExA */
FreeRDP_WTSCloseServer, /* CloseServer */
FreeRDP_WTSEnumerateSessionsW, /* EnumerateSessionsW */
FreeRDP_WTSEnumerateSessionsA, /* EnumerateSessionsA */
FreeRDP_WTSEnumerateSessionsExW, /* EnumerateSessionsExW */
FreeRDP_WTSEnumerateSessionsExA, /* EnumerateSessionsExA */
FreeRDP_WTSEnumerateProcessesW, /* EnumerateProcessesW */
FreeRDP_WTSEnumerateProcessesA, /* EnumerateProcessesA */
FreeRDP_WTSTerminateProcess, /* TerminateProcess */
FreeRDP_WTSQuerySessionInformationW, /* QuerySessionInformationW */
FreeRDP_WTSQuerySessionInformationA, /* QuerySessionInformationA */
FreeRDP_WTSQueryUserConfigW, /* QueryUserConfigW */
FreeRDP_WTSQueryUserConfigA, /* QueryUserConfigA */
FreeRDP_WTSSetUserConfigW, /* SetUserConfigW */
FreeRDP_WTSSetUserConfigA, /* SetUserConfigA */
FreeRDP_WTSSendMessageW, /* SendMessageW */
FreeRDP_WTSSendMessageA, /* SendMessageA */
FreeRDP_WTSDisconnectSession, /* DisconnectSession */
FreeRDP_WTSLogoffSession, /* LogoffSession */
FreeRDP_WTSShutdownSystem, /* ShutdownSystem */
FreeRDP_WTSWaitSystemEvent, /* WaitSystemEvent */
FreeRDP_WTSVirtualChannelOpen, /* VirtualChannelOpen */
FreeRDP_WTSVirtualChannelOpenEx, /* VirtualChannelOpenEx */
FreeRDP_WTSVirtualChannelClose, /* VirtualChannelClose */
FreeRDP_WTSVirtualChannelRead, /* VirtualChannelRead */
FreeRDP_WTSVirtualChannelWrite, /* VirtualChannelWrite */
FreeRDP_WTSVirtualChannelPurgeInput, /* VirtualChannelPurgeInput */
FreeRDP_WTSVirtualChannelPurgeOutput, /* VirtualChannelPurgeOutput */
FreeRDP_WTSVirtualChannelQuery, /* VirtualChannelQuery */
FreeRDP_WTSFreeMemory, /* FreeMemory */
FreeRDP_WTSRegisterSessionNotification, /* RegisterSessionNotification */
FreeRDP_WTSUnRegisterSessionNotification, /* UnRegisterSessionNotification */
FreeRDP_WTSRegisterSessionNotificationEx, /* RegisterSessionNotificationEx */
FreeRDP_WTSUnRegisterSessionNotificationEx, /* UnRegisterSessionNotificationEx */
FreeRDP_WTSQueryUserToken, /* QueryUserToken */
FreeRDP_WTSFreeMemoryExW, /* FreeMemoryExW */
FreeRDP_WTSFreeMemoryExA, /* FreeMemoryExA */
FreeRDP_WTSEnumerateProcessesExW, /* EnumerateProcessesExW */
FreeRDP_WTSEnumerateProcessesExA, /* EnumerateProcessesExA */
FreeRDP_WTSEnumerateListenersW, /* EnumerateListenersW */
FreeRDP_WTSEnumerateListenersA, /* EnumerateListenersA */
FreeRDP_WTSQueryListenerConfigW, /* QueryListenerConfigW */
FreeRDP_WTSQueryListenerConfigA, /* QueryListenerConfigA */
FreeRDP_WTSCreateListenerW, /* CreateListenerW */
FreeRDP_WTSCreateListenerA, /* CreateListenerA */
FreeRDP_WTSSetListenerSecurityW, /* SetListenerSecurityW */
FreeRDP_WTSSetListenerSecurityA, /* SetListenerSecurityA */
FreeRDP_WTSGetListenerSecurityW, /* GetListenerSecurityW */
FreeRDP_WTSGetListenerSecurityA, /* GetListenerSecurityA */
FreeRDP_WTSEnableChildSessions, /* EnableChildSessions */
FreeRDP_WTSIsChildSessionsEnabled, /* IsChildSessionsEnabled */
FreeRDP_WTSGetChildSessionId, /* GetChildSessionId */
FreeRDP_WTSGetActiveConsoleSessionId, /* GetActiveConsoleSessionId */
FreeRDP_WTSLogonUser,
FreeRDP_WTSLogoffUser,
FreeRDP_WTSStartRemoteControlSessionExW,
FreeRDP_WTSStartRemoteControlSessionExA
};
PWtsApiFunctionTable FreeRDP_InitWtsApi(void)
{
return &FreeRDP_WtsApiFunctionTable;
}