Blame channels/drdynvc/server/drdynvc_main.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * Dynamic Virtual Channel Extension
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 * Copyright 2015 Thincast Technologies GmbH
Packit 1fb8d4
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/print.h>
Packit 1fb8d4
#include <winpr/stream.h>
Packit 1fb8d4
#include <freerdp/channels/log.h>
Packit 1fb8d4
Packit 1fb8d4
#include "drdynvc_main.h"
Packit 1fb8d4
Packit 1fb8d4
#define TAG CHANNELS_TAG("drdynvc.server")
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
static DWORD WINAPI drdynvc_server_thread(LPVOID arg)
Packit 1fb8d4
{
Packit 1fb8d4
#if 0
Packit 1fb8d4
	wStream* s;
Packit 1fb8d4
	DWORD status;
Packit 1fb8d4
	DWORD nCount;
Packit 1fb8d4
	void* buffer;
Packit 1fb8d4
	HANDLE events[8];
Packit 1fb8d4
	HANDLE ChannelEvent;
Packit 1fb8d4
	DWORD BytesReturned;
Packit 1fb8d4
	DrdynvcServerContext* context;
Packit 1fb8d4
	UINT error = ERROR_INTERNAL_ERROR;
Packit 1fb8d4
	context = (DrdynvcServerContext*) arg;
Packit 1fb8d4
	buffer = NULL;
Packit 1fb8d4
	BytesReturned = 0;
Packit 1fb8d4
	ChannelEvent = NULL;
Packit 1fb8d4
Packit 1fb8d4
	s = Stream_New(NULL, 4096);
Packit 1fb8d4
Packit 1fb8d4
	if (!s)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "Stream_New failed!");
Packit 1fb8d4
		ExitThread((DWORD) CHANNEL_RC_NO_MEMORY);
Packit 1fb8d4
		return CHANNEL_RC_NO_MEMORY;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle,
Packit 1fb8d4
	                           &buffer, &BytesReturned) == TRUE)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (BytesReturned == sizeof(HANDLE))
Packit 1fb8d4
			CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
Packit 1fb8d4
Packit 1fb8d4
		WTSFreeMemory(buffer);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	nCount = 0;
Packit 1fb8d4
	events[nCount++] = ChannelEvent;
Packit 1fb8d4
	events[nCount++] = context->priv->StopEvent;
Packit 1fb8d4
Packit 1fb8d4
	while (1)
Packit 1fb8d4
	{
Packit 1fb8d4
		status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
Packit 1fb8d4
Packit 1fb8d4
		if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
Packit 1fb8d4
		{
Packit 1fb8d4
			error = CHANNEL_RC_OK;
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0,
Packit 1fb8d4
		                           &BytesReturned))
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (BytesReturned < 1)
Packit 1fb8d4
			continue;
Packit 1fb8d4
Packit 1fb8d4
		if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
Packit 1fb8d4
		                           (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_Free(s, TRUE);
Packit 1fb8d4
	ExitThread((DWORD) error);
Packit 1fb8d4
#endif
Packit 1fb8d4
	// WTF ... this code only reads data into the stream until there is no more memory
Packit 1fb8d4
	ExitThread(0);
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Function description
Packit 1fb8d4
 *
Packit 1fb8d4
 * @return 0 on success, otherwise a Win32 error code
Packit 1fb8d4
 */
Packit 1fb8d4
static UINT drdynvc_server_start(DrdynvcServerContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm,
Packit 1fb8d4
	                               WTS_CURRENT_SESSION, "drdynvc");
Packit 1fb8d4
Packit 1fb8d4
	if (!context->priv->ChannelHandle)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WTSVirtualChannelOpen failed!");
Packit 1fb8d4
		return CHANNEL_RC_NO_MEMORY;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!(context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "CreateEvent failed!");
Packit 1fb8d4
		return ERROR_INTERNAL_ERROR;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!(context->priv->Thread = CreateThread(NULL, 0, drdynvc_server_thread, (void*) context, 0, NULL)))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "CreateThread failed!");
Packit 1fb8d4
		CloseHandle(context->priv->StopEvent);
Packit 1fb8d4
		context->priv->StopEvent = NULL;
Packit 1fb8d4
		return ERROR_INTERNAL_ERROR;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return CHANNEL_RC_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Function description
Packit 1fb8d4
 *
Packit 1fb8d4
 * @return 0 on success, otherwise a Win32 error code
Packit 1fb8d4
 */
Packit 1fb8d4
static UINT drdynvc_server_stop(DrdynvcServerContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT error;
Packit 1fb8d4
	SetEvent(context->priv->StopEvent);
Packit 1fb8d4
Packit 1fb8d4
	if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
Packit 1fb8d4
	{
Packit 1fb8d4
		error = GetLastError();
Packit 1fb8d4
		WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error);
Packit 1fb8d4
		return error;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	CloseHandle(context->priv->Thread);
Packit 1fb8d4
	return CHANNEL_RC_OK;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
DrdynvcServerContext* drdynvc_server_context_new(HANDLE vcm)
Packit 1fb8d4
{
Packit 1fb8d4
	DrdynvcServerContext* context;
Packit 1fb8d4
	context = (DrdynvcServerContext*) calloc(1, sizeof(DrdynvcServerContext));
Packit 1fb8d4
Packit 1fb8d4
	if (context)
Packit 1fb8d4
	{
Packit 1fb8d4
		context->vcm = vcm;
Packit 1fb8d4
		context->Start = drdynvc_server_start;
Packit 1fb8d4
		context->Stop = drdynvc_server_stop;
Packit 1fb8d4
		context->priv = (DrdynvcServerPrivate*) calloc(1, sizeof(DrdynvcServerPrivate));
Packit 1fb8d4
Packit 1fb8d4
		if (!context->priv)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "calloc failed!");
Packit 1fb8d4
			free(context);
Packit 1fb8d4
			return NULL;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "calloc failed!");
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return context;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void drdynvc_server_context_free(DrdynvcServerContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (context)
Packit 1fb8d4
	{
Packit 1fb8d4
		free(context->priv);
Packit 1fb8d4
		free(context);
Packit 1fb8d4
	}
Packit 1fb8d4
}